diff --git a/.github/workflows/admin.yaml b/.github/workflows/admin.yaml index 239535bbb..00fe4e2a8 100644 --- a/.github/workflows/admin.yaml +++ b/.github/workflows/admin.yaml @@ -13,8 +13,8 @@ on: workflow_call: jobs: - eslint: - name: ESLint + lint: + name: Lint runs-on: ubuntu-latest steps: - uses: shopware/github-actions/setup-extension@main @@ -33,7 +33,9 @@ jobs: } - run: | composer -d custom/plugins/${{ github.event.repository.name }} run admin:install - composer -d custom/plugins/${{ github.event.repository.name }} run admin:lint + composer -d custom/plugins/${{ github.event.repository.name }} run lint:admin + composer -d custom/plugins/${{ github.event.repository.name }} run format:admin + composer -d custom/plugins/${{ github.event.repository.name }} run format:md stylelint: name: Stylelint @@ -55,7 +57,7 @@ jobs: } - run: | composer -d custom/plugins/${{ github.event.repository.name }} run admin:install - composer -d custom/plugins/${{ github.event.repository.name }} run admin:lint:scss + composer -d custom/plugins/${{ github.event.repository.name }} run lint:admin:scss jest: name: Jest diff --git a/.github/workflows/check-pr-title.yml b/.github/workflows/check-pr-title.yml new file mode 100644 index 000000000..6da327569 --- /dev/null +++ b/.github/workflows/check-pr-title.yml @@ -0,0 +1,33 @@ +name: Check PR title + +on: + pull_request: + types: + - opened + - reopened + - edited + - synchronize + +permissions: + pull-requests: read + +jobs: + lint: + runs-on: ubuntu-latest + steps: + - uses: amannn/action-semantic-pull-request@48f256284bd46cdaab1048c3721360e808335d50 # 6.1.1 + with: + types: | + feat + fix + chore + docs + style + refactor + perf + test + build + ci + revert + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/integration.yaml b/.github/workflows/integration.yaml index 4d8fd2acd..7bef6fd32 100644 --- a/.github/workflows/integration.yaml +++ b/.github/workflows/integration.yaml @@ -55,7 +55,7 @@ jobs: } - name: Import SW5 TestData DB working-directory: custom/plugins/${{ github.event.repository.name }}/tests - run: mysql -uroot < testData/sw55.sql + run: mysql -uroot < _fixtures/database/sw55.sql - name: Run PHPUnit working-directory: custom/plugins/${{ github.event.repository.name }} run: php -d pcov.enabled=1 -d pcov.directory=${PWD} -d pcov.exclude='~(vendor|tests|node_modules)~' ${GITHUB_WORKSPACE}/vendor/bin/phpunit --configuration phpunit.xml.dist @@ -118,7 +118,7 @@ jobs: run: | composer run build:js:admin cd custom/plugins/${{ github.event.repository.name }}/tests - mysql -uroot < testData/sw55.sql + mysql -uroot < _fixtures/database/sw55.sql - name: Install playwright working-directory: custom/plugins/${{ github.event.repository.name }}/tests/acceptance run: | diff --git a/.gitignore b/.gitignore index 5d53cb79f..ba9a778e3 100644 --- a/.gitignore +++ b/.gitignore @@ -1,15 +1,32 @@ -.idea -.vscode -coverage/ -.phpunit.cache -.phpunit.result.cache -vendor -node_modules -phpstan.neon +# ide +.idea/ +.vscode/ + +# os +.DS_Store + +# node +node_modules/ *.hot-update.js -/var/ + +# php +vendor/ +phpstan.neon composer.lock -src/Resources/public/administration/ +.phpunit.cache +.phpunit.result.cache + +# tests +coverage/ + +# build src/Resources/public/static/ +src/Resources/public/administration/ +src/Resources/app/administration/.tmp + +# runtime +/var/ .env + +# plugin /migration_assistant.cache diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml deleted file mode 100644 index 1657d96f2..000000000 --- a/.gitlab-ci.yml +++ /dev/null @@ -1,199 +0,0 @@ -variables: - PLUGIN_NAME: SwagMigrationAssistant - PLATFORM_MIN_VERSION: 'v6.6.1.0' - PLATFORM_DEFAULT_VERSION: 'trunk' - PLATFORM_BRANCH: $PLATFORM_DEFAULT_VERSION - DEV_IMAGE: - value: ${CI_REGISTRY}/infrastructure/docker-base/ci-build:latest - NODE_VERSION: 20 - -include: - - project: 'shopware/6/product/platform' - ref: 'trunk' - file: '.gitlab/templates/plugin.yml' -# - component: gitlab.shopware.com/infrastructure/ci-component-library/kaniko-amd64@trunk -# inputs: -# job-suffix: "" -# stage: E2E -# destination-image: "${CI_REGISTRY_IMAGE}/ci-e2e" -# destination-tag: "${PLATFORM_BRANCH}-${CI_PIPELINE_ID}" -# dockerfile: .gitlab/Dockerfile -# enable-scan: "false" -# cache: "false" -# build-arg: "BASE_IMAGE=$PLATFORM_BASE_IMAGE" -# extra-args: "--build-arg CI_JOB_TOKEN=$CI_JOB_TOKEN" - -Danger: - stage: test - image: - name: ghcr.io/shyim/danger-php:latest - entrypoint: [ "" ] - rules: - - if: '$CI_PIPELINE_SOURCE == "merge_request_event"' - before_script: [ ] - script: - - danger ci - -ecs: - stage: test - script: - - composer ecs - -Eslint (administration): - stage: test - variables: - APP_ENV: prod - ADMIN_PATH: $CI_PROJECT_DIR/src/Administration/Resources/app/administration - STOREFRONT_PATH: $CI_PROJECT_DIR/src/Storefront/Resources/app/storefront - script: - - '(cd $ADMIN_PATH && npm ci)' - - $CI_PROJECT_DIR/bin/console framework:schema -s 'entity-schema' $ADMIN_PATH/test/_mocks_/entity-schema.json - - npm --prefix $ADMIN_PATH run unit-setup - - composer admin:install - - composer admin:lint - -jest (administration): - rules: - # exists does not support variables, so we cannot use ${PLUGIN_SOURCE_DIR} here - - exists: - - tests/Jest/jest.config.js - variables: - APP_ENV: prod - ADMIN_PATH: $CI_PROJECT_DIR/src/Administration/Resources/app/administration - STOREFRONT_PATH: $CI_PROJECT_DIR/src/Storefront/Resources/app/storefront - script: - - '(cd $ADMIN_PATH && npm ci)' - - $CI_PROJECT_DIR/bin/console framework:schema -s 'entity-schema' $ADMIN_PATH/test/_mocks_/entity-schema.json - - npm --prefix $ADMIN_PATH run unit-setup - - composer admin:install - - composer admin:unit -- --ci - coverage: '/^\s?All files[^|]*\|[^|]*\s+([\d\.]+)/' - artifacts: - paths: - # allow inspection of the coverage report, otherwise it's not accessible - - custom/plugins/SwagMigrationAssistant/coverage/cobertura-coverage.xml - reports: - junit: - - custom/plugins/SwagMigrationAssistant/coverage/junit.xml - coverage_report: - coverage_format: cobertura - path: custom/plugins/SwagMigrationAssistant/coverage/cobertura-coverage.xml - -phpunit: - script: - - apt-get update && apt-get --assume-yes install default-mysql-client - - cd tests - - cd - - - mysql --skip_ssl -uroot -p"$MYSQL_ROOT_PASSWORD" --host mysql < tests/testData/sw55.sql - - php - -d pcov.enabled=1 -d pcov.directory=$PWD -d pcov.exclude='~(vendor|tests|node_modules)~' - ${PROJECT_ROOT}/vendor/bin/phpunit - --configuration phpunit.xml.dist - --log-junit ${CI_PROJECT_DIR}/phpunit.junit.xml - --colors=never - --coverage-cobertura ${CI_PROJECT_DIR}/cobertura.xml - --coverage-text #| grep -v -E '^Shopware\\|^ Methods:' # do not output covered files lines - parallel: - matrix: - - PLATFORM_BRANCH: [ $PLATFORM_MIN_VERSION, $PLATFORM_DEFAULT_VERSION ] - -phpstan: - script: - - composer dump-autoload --dev - - composer phpstan - -smoke-test: - stage: test - needs: [] - rules: - - !reference [.rules, skip] - - when: always - script: - - cd ../../.. - - php bin/console plugin:refresh - - php bin/console plugin:install --activate --clearCache ${PLUGIN_NAME} - - php bin/console plugin:uninstall ${PLUGIN_NAME} - -# disabled acceptance test, will be active as GH Action again after move to GitHub -#build image: -# variables: -# PLATFORM_BASE_IMAGE: ${CI_REGISTRY}/shopware/6/product/platform/ci-e2e:${PLATFORM_BRANCH} -# rules: -# # not supported, the downstream pipeline should find any issues anyway -# - if: "$CI_MERGE_REQUEST_LABELS =~ /.*branch::platform::match.*/" -# when: never -# - if: "$PARENT_PIPELINE_ID" -# when: never -# - when: always -# needs: [] -# parallel: -# matrix: -# - PLATFORM_BRANCH: [ $PLATFORM_MIN_VERSION, $PLATFORM_DEFAULT_VERSION ] -# -#build image downstream: -# extends: build image -# rules: -# - if: "$PARENT_PIPELINE_ID" -# needs: -# - pipeline: $PARENT_PIPELINE_ID -# job: build image -# artifacts: false -# -#acceptance: -# image: mcr.microsoft.com/playwright:v1.44.0-jammy -# stage: E2E -# needs: -# - job: build image -# optional: true -# - job: build image downstream -# optional: true -# rules: -# # not supported, the downstream pipeline should find any issues anyway -# - if: "$CI_MERGE_REQUEST_LABELS =~ /.*branch::platform::match.*/" -# when: never -# - when: always -# services: -# - name: mysql:8.3 -# alias: database -# entrypoint: -# [ -# "sh", -# "-c", -# "docker-entrypoint.sh mysqld --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci --default-authentication-plugin=mysql_native_password --sql-require-primary-key=ON", -# ] -# - name: redis:7.0 -# alias: redis -# - name: "${CI_REGISTRY_IMAGE}/ci-e2e:${PLATFORM_BRANCH}-${CI_PIPELINE_ID}" -# alias: shopware.test -# variables: -# DATABASE_URL: mysql://root:app@database:3306/root -# parallel: -# matrix: -# - PLATFORM_BRANCH: [ $PLATFORM_MIN_VERSION, $PLATFORM_DEFAULT_VERSION ] -# variables: -# # CI_DEBUG_SERVICES: "true" # This can be used to display the output of all service containers for debugging -# APP_ENV: prod -# SHOPWARE_HTTP_CACHE_ENABLED: 0 -# SHOPWARE_DISABLE_UPDATE_CHECK: "true" -# PROJECT_ROOT: /var/www/html -# MYSQL_ROOT_PASSWORD: app -# DATABASE_URL: mysql://root:app@database:3306/root -# APP_URL: http://shopware.test:8000 -# APP_DEBUG: 1 -# before_script: -# - cd tests/acceptance -# - npm ci -# script: -# - npx playwright test --workers=1 -# after_script: -# - | -# echo "Link to HTML report" -# echo "-------------------------------------------------------------------------------------------------------------------------------------------------------" -# echo "https://shopware.pages.apps.shopware.io/-/6/services/$CI_PROJECT_NAME/-/jobs/$CI_JOB_ID/artifacts/tests/acceptance/playwright-report/index.html" -# echo "-------------------------------------------------------------------------------------------------------------------------------------------------------" -# artifacts: -# expire_in: 1 day -# when: always -# paths: -# - $CI_PROJECT_DIR/tests/acceptance/test-results/* -# - $CI_PROJECT_DIR/tests/acceptance/playwright-report/* diff --git a/.gitlab/Dockerfile b/.gitlab/Dockerfile deleted file mode 100644 index 0aa0f6207..000000000 --- a/.gitlab/Dockerfile +++ /dev/null @@ -1,34 +0,0 @@ -#syntax=docker/dockerfile:1.4 - -ARG BASE_IMAGE -FROM ${BASE_IMAGE} as base-image - -FROM ghcr.io/friendsofshopware/shopware-cli:latest-php-8.2 as build -ARG CI_JOB_TOKEN - -COPY --from=base-image /var/www/html /src -WORKDIR /src - -COPY . /src/custom/plugins/SwagMigrationAssistant - -ENV COMPOSER_ALLOW_SUPERUSER=1 - -RUN /src/vendor/bin/composer -d /src/custom/plugins/SwagMigrationAssistant require --no-update 'shopware/core:*' \ - && /src/vendor/bin/composer require --no-plugins --no-scripts -o swag/migration-assistant \ - && rm -Rf /src/var/cache/* \ - && /usr/local/bin/entrypoint.sh shopware-cli project admin-build /src \ - && /usr/local/bin/entrypoint.sh shopware-cli project storefront-build --skip-theme-compile /src \ - && find . -name 'node_modules' -type d -prune -exec rm -rf '{}' + \ - && find . -name '.git' -type d -prune -exec rm -rf '{}' + \ - && rm -Rf /src/public/bundles || true - -FROM base-image - -COPY --from=build --chown=www-data --link /src /var/www/html - -USER root -RUN apk add --no-cache mysql-client - -USER www-data - -ADD .gitlab/post_install_migration_assistant.sh /usr/local/shopware/post_install.d/99_post_install_migration_assistant.sh diff --git a/.gitlab/install_test_data.php b/.gitlab/install_test_data.php deleted file mode 100644 index 25eec317c..000000000 --- a/.gitlab/install_test_data.php +++ /dev/null @@ -1,55 +0,0 @@ -SW6, where the default folder id was set wrongly. This includes changes to the way the folder structure is migrated # 13.2.0 + - MIG-1035 - Changed the premapping assignment in the administration, which should fix issues with assignment on later pagination pages and changes getting lost with newly selected data -- MIG-1042 - Adding a notice to clear the cache when the Shopware 5 Connector can't be found. +- MIG-1042 - Adding a notice to clear the cache when the Shopware 5 Connector can't be found - MIG-1045 - Fix displayed percentage status while reading data - MIG-1046 - Fixed an issue related to the validation of json fields for a migration run, which could prevent starting a migration in the latest shopware version # 13.1.0 -- MIG-981 - Media migration now uses the system's temporary directory to download files. -- MIG-1016 - Improves the warnings for different default currency and default language in the data selection. -- MIG-1016 - Added new block `{% block swag_migration_confirm_warning_alert %}` in `swag-migration/component/card/swag-migration-confirm-warning/swag-migration-confirm-warning.html.twig`. -- MIG-1037 - Fixes a rare issue that in certain situations not all entities are migrated (some were skipped). Was detected during translations of SW5. - + +- MIG-981 - Media migration now uses the system's temporary directory to download files +- MIG-1016 - Improves the warnings for different default currency and default language in the data selection +- MIG-1016 - Added new block `{% block swag_migration_confirm_warning_alert %}` in `swag-migration/component/card/swag-migration-confirm-warning/swag-migration-confirm-warning.html.twig` +- MIG-1037 - Fixes a rare issue that in certain situations not all entities are migrated (some were skipped). Was detected during translations of SW5 + # 13.0.0 + - MIG-945 - [BREAKING] Changed method name `getMedia` to `setMedia` in `SwagMigrationAssistant\Profile\Shopware\Converter\PropertyGroupOptionConverter` - MIG-945 - [BREAKING] Removed cli command `migration:migrate` use `migration:start` instead - MIG-945 - [BREAKING] Changed method `writePremapping` of `SwagMigrationAssistant\Controller\PremappingController` @@ -124,6 +144,7 @@ - MIG-1011 - Ensure database attributes (like stringify fetches) are always set on local gateway connections # 12.0.0 + - MIG-983 - Fix migration of shop bounded customers - MIG-983 - [BREAKING] Changed method name `getAddresses` to `applyAddresses` in `\SwagMigrationAssistant\Profile\Shopware\Converter\OrderConverter` - MIG-983 - [BREAKING] Changed method name `getCountryTranslation` to `applyCountryTranslation` in `\SwagMigrationAssistant\Profile\Shopware\Converter\OrderConverter` @@ -132,16 +153,18 @@ - MIG-989 - Improve migration of Media files - MIG-989 - [BREAKING] Added method `filterUnwrittenData` to `\SwagMigrationAssistant\Migration\Media\MediaFileServiceInterface` - MIG-990 - Don't let exceptions abort handling of ProcessMediaMessage -- MIG-990 - [BREAKING] Changed constructor of `BaseMediaService`, added `EntityRepository $mediaFileRepository` as new parameter, updated all extending classes. +- MIG-990 - [BREAKING] Changed constructor of `BaseMediaService`, added `EntityRepository $mediaFileRepository` as new parameter, updated all extending classes - MIG-990 - [BREAKING] Added method `setProcessedFlag` in `BaseMediaService` and updated all media processors to use this method - MIG-990 - [BREAKING] Moved `BaseMediaService` to `SwagMigrationAssistant\Migration\Media\Processor` namespace - MIG-992 - Fix migration of product seo data - MIG-1006 - Fix migration of product covers # 11.0.1 + - MIG-988 - A bug in the premapping UI has been fixed to remain compatible with the latest platform version # 11.0.0 + - MIG-951 - Improve the language migration from Shopware 6 to Shopware 6 so the default language is no longer overwritten - MIG-951 - [BREAKING] Changes the access modifier of the function `\SwagMigrationAssistant\Profile\Shopware6\Converter\LanguageConverter::convertData` from public to protected - MIG-943 - Fix migration of calculated shipping costs from Shopware 5 @@ -149,23 +172,26 @@ - MIG-943 - [BREAKING] Rename method in class `\SwagMigrationAssistant\Profile\Shopware\Converter\OrderConverter` from `getCountryTranslation` to `applyCountryTranslation` - MIG-943 - [BREAKING] Rename method in class `\SwagMigrationAssistant\Profile\Shopware\Converter\OrderConverter` from `getCountryStateTranslation` to `applyCountryStateTranslation` - MIG-943 - [BREAKING] Changed thrown exception from `AssociationEntityRequiredMissingException` to `SwagMigrationAssistant\Exception\MigrationException::associationMissing` in method `\SwagMigrationAssistant\Profile\Shopware\Converter\OrderConverter::convert` -- MIG-967, MIG-866 - Improving the migration of order documents +- MIG-967, MIG-866 - Improving the migration of order documents # 10.0.1 + - MIG-971 - Fix compatibility with Shopware 6.6.0.x # 10.0.0 -- NEXT-34526 - [BREAKING] Added native type to `result` parameter of `SwagMigrationAssistant\DataProvider\Provider\Data\AbstractProvider::cleanupSearchResult` method. -- NEXT-34526 - [BREAKING] Removed `DataProvider/Exception/ProviderHasNoTableAccessException.php`, use `SwagMigrationAssistant\Exception\MigrationException::providerHasNoTableAccess` instead. -- NEXT-34526 - [BREAKING] Removed `Profile/Shopware/Exception/ParentEntityForChildNotFoundException.php`, use `SwagMigrationAssistant\Exception\MigrationException::parentEntityForChildNotFound` instead. -- NEXT-34526 - [BREAKING] Changed method name `getMediaTranslation` to `addMediaTranslation` in `SwagMigrationAssistant\Profile\Shopware\Converter\CategoryConverter`. -- NEXT-34526 - [BREAKING] Changed method name `getAttribute` to `addAttribute` in `\SwagMigrationAssistant\Profile\Shopware\Converter\TranslationConverter`. -- NEXT-34526 - [BREAKING] Changed parameter name `blacklist` to `excludeList` of method `SwagMigrationAssistant\Profile\Shopware\Converter\ShopwareConverter::getAttributes`. + +- NEXT-34526 - [BREAKING] Added native type to `result` parameter of `SwagMigrationAssistant\DataProvider\Provider\Data\AbstractProvider::cleanupSearchResult` method +- NEXT-34526 - [BREAKING] Removed `DataProvider/Exception/ProviderHasNoTableAccessException.php`, use `SwagMigrationAssistant\Exception\MigrationException::providerHasNoTableAccess` instead +- NEXT-34526 - [BREAKING] Removed `Profile/Shopware/Exception/ParentEntityForChildNotFoundException.php`, use `SwagMigrationAssistant\Exception\MigrationException::parentEntityForChildNotFound` instead +- NEXT-34526 - [BREAKING] Changed method name `getMediaTranslation` to `addMediaTranslation` in `SwagMigrationAssistant\Profile\Shopware\Converter\CategoryConverter` +- NEXT-34526 - [BREAKING] Changed method name `getAttribute` to `addAttribute` in `\SwagMigrationAssistant\Profile\Shopware\Converter\TranslationConverter` +- NEXT-34526 - [BREAKING] Changed parameter name `blacklist` to `excludeList` of method `SwagMigrationAssistant\Profile\Shopware\Converter\ShopwareConverter::getAttributes` - MIG-868 - Improvement of the product migration, the gross purchase price is now calculated -- MIG-966 - [BREAKING] Moved the source files into the `src` directory and renamed the `Test` directory to `tests` without breaking namespaces, but you may need to reactivate or reinstall the plugin. This fixed a bug in our deployment process to properly build the plugin. -- MIG-930 - Improved cross-selling migration, cross-selling no longer overwrites existing cross-selling if there are no changes. +- MIG-966 - [BREAKING] Moved the source files into the `src` directory and renamed the `Test` directory to `tests` without breaking namespaces, but you may need to reactivate or reinstall the plugin. This fixed a bug in our deployment process to properly build the plugin +- MIG-930 - Improved cross-selling migration, cross-selling no longer overwrites existing cross-selling if there are no changes # 9.0.0 + - MIG-848 - Improving the assigning of products to sales channel via sub- and language shops - MIG-920 - Changed supported Shopware 6 version to 6.6 and made adjustments to the profiles - MIG-920 - Added `Migration/Gateway/HttpClientInterface` to unify the usage of HTTP clients @@ -195,6 +221,7 @@ - MIG-934 - [BREAKING] Changed `Controller/DataProviderController.php` to final # 8.0.0 + - MIG-274 - Fix migration of cross selling - MIG-825 - Improve performance of the migration of orders - MIG-825 - Added option `step-size` to the cli command `migration:migrate` of `Command/MigrationCommand.php` @@ -226,109 +253,130 @@ - MIG-938 - Fixes wrong calculation when migrating shipping costs # 7.0.2 + - MIG-908 - Fix Shopware 6 migration of `system_config` entities which should not be migrated between different shops # 7.0.1 + - MIG-907 - Fix Shopware 6 profile name in connections # 7.0.0 + - NEXT-31367 - Improve the ConnectionFactory to work more stable -- MIG-881 - Fix bug for converting shipping methods and shipping costs and also migrate shipping methods with a unknown calculation type. -- MIG-878 - Fix migration from SW6.5 to SW6.5. Only same major migrations are supported. -- MIG-905 - Hotfix / known issue for SW6->SW6: `canonicalProductId` of `product` isn't migrated but doesn't prevent migration of products for now. -- MIG-905 - Hotfix / known issue for SW6->SW6: `cmsPageId` of `product` isn't migrated but doesn't prevent migration of products for now. -- MIG-905 - Hotfix / known issue for SW6->SW6: `promotionId` of line items of an order aren't migrated but doesn't prevent migration of orders for now. -- MIG-881 - [BREAKING] Removed method `getDefaultAvailabilityRule` of `Migration/Mapping/MappingServiceInterface.php` and all implementors. Use the premapping of `default_shipping_availability_rule` instead. -- MIG-881 - [BREAKING] Removed parameter `customerRepository` of `Migration/MessageQueue/OrderCountIndexer.php`. -- MIG-878 - [BREAKING] Removed all classes under `Profile/Shopware63`. Use classes under `Profile/Shopware6` instead. -- MIG-878 - [BREAKING] Changed all converters under `Profile/Shopware6/Converter` to be not `abstract` and implement the corresponding `supports` methods. These now replace the old converters under `Profile/Shopware63/Converter`. -- MIG-878 - [BREAKING] Renamed `Profile/Shopware63/Shopware63Profile.php` to `Profile/Shopware6/Shopware6MajorProfile`. -- MIG-878 - [BREAKING] Changed `Profile/Shopware6/Shopware6MajorProfile` to support only the current SW6 major version. -- MIG-878 - [BREAKING] Changed `Profile/Shopware6/Shopware6MajorProfile` to now return `shopware6major` on `getName`. -- MIG-878 - [BREAKING] Renamed `swag-migration-profile-shopware6-api-credential-form` vue component to `swag-migration-profile-shopware6major-api-credential-form`. -- MIG-878 - [BREAKING] Renamed `swag-migration-profile-shopware6-api-page-information` vue component to `swag-migration-profile-shopware6major-api-page-information`. -- MIG-878 - [BREAKING] Removed `swag-migration-profile-shopware63-api-credential-form` vue component. -- MIG-878 - [BREAKING] Removed `swag-migration-profile-shopware63-api-page-information` vue component. -- MIG-878 - [BREAKING] Removed `Profile/Shopware6/DataSelection/DataSet/ProductMainVariantRelationDataSet.php` because it is already migrated with the `product` entity in SW6. -- MIG-878 - [BREAKING] Removed `DataProvider/Provider/Data/ProductMainVariantRelationProvider.php` because it is already migrated with the `product` entity in SW6. -- MIG-878 - [BREAKING] Removed `Profile/Shopware6/Gateway/Api/Reader/ProductMainVariantRelationReader.php` because it is already migrated with the `product` entity in SW6. -- MIG-878 - [BREAKING] Removed `Profile/Shopware6/Converter/ProductMainVariantRelationConverter.php` because it is already migrated with the `product` entity in SW6. +- MIG-881 - Fix bug for converting shipping methods and shipping costs and also migrate shipping methods with a unknown calculation type +- MIG-878 - Fix migration from SW6.5 to SW6.5. Only same major migrations are supported +- MIG-905 - Hotfix / known issue for SW6->SW6: `canonicalProductId` of `product` isn't migrated but doesn't prevent migration of products for now +- MIG-905 - Hotfix / known issue for SW6->SW6: `cmsPageId` of `product` isn't migrated but doesn't prevent migration of products for now +- MIG-905 - Hotfix / known issue for SW6->SW6: `promotionId` of line items of an order aren't migrated but doesn't prevent migration of orders for now +- MIG-881 - [BREAKING] Removed method `getDefaultAvailabilityRule` of `Migration/Mapping/MappingServiceInterface.php` and all implementors. Use the premapping of `default_shipping_availability_rule` instead +- MIG-881 - [BREAKING] Removed parameter `customerRepository` of `Migration/MessageQueue/OrderCountIndexer.php` +- MIG-878 - [BREAKING] Removed all classes under `Profile/Shopware63`. Use classes under `Profile/Shopware6` instead +- MIG-878 - [BREAKING] Changed all converters under `Profile/Shopware6/Converter` to be not `abstract` and implement the corresponding `supports` methods. These now replace the old converters under `Profile/Shopware63/Converter` +- MIG-878 - [BREAKING] Renamed `Profile/Shopware63/Shopware63Profile.php` to `Profile/Shopware6/Shopware6MajorProfile` +- MIG-878 - [BREAKING] Changed `Profile/Shopware6/Shopware6MajorProfile` to support only the current SW6 major version +- MIG-878 - [BREAKING] Changed `Profile/Shopware6/Shopware6MajorProfile` to now return `shopware6major` on `getName` +- MIG-878 - [BREAKING] Renamed `swag-migration-profile-shopware6-api-credential-form` vue component to `swag-migration-profile-shopware6major-api-credential-form` +- MIG-878 - [BREAKING] Renamed `swag-migration-profile-shopware6-api-page-information` vue component to `swag-migration-profile-shopware6major-api-page-information` +- MIG-878 - [BREAKING] Removed `swag-migration-profile-shopware63-api-credential-form` vue component +- MIG-878 - [BREAKING] Removed `swag-migration-profile-shopware63-api-page-information` vue component +- MIG-878 - [BREAKING] Removed `Profile/Shopware6/DataSelection/DataSet/ProductMainVariantRelationDataSet.php` because it is already migrated with the `product` entity in SW6 +- MIG-878 - [BREAKING] Removed `DataProvider/Provider/Data/ProductMainVariantRelationProvider.php` because it is already migrated with the `product` entity in SW6 +- MIG-878 - [BREAKING] Removed `Profile/Shopware6/Gateway/Api/Reader/ProductMainVariantRelationReader.php` because it is already migrated with the `product` entity in SW6 +- MIG-878 - [BREAKING] Removed `Profile/Shopware6/Converter/ProductMainVariantRelationConverter.php` because it is already migrated with the `product` entity in SW6 # 6.0.1 + - MIG-887 - Improve performance of the endpoint, which captures all data to be written afterwards # 6.0.0 + - MIG-879 - Fix tax free order migration from SW5 -- MIG-859 - [BREAKING] Removed method `pushMapping` of `Migration/Mapping/MappingServiceInterface.php` and all implementors. Use `getOrCreateMapping` instead. -- MIG-859 - [BREAKING] Removed method `pushValueMapping` of `Migration/Mapping/MappingServiceInterface.php` and all implementors. Use `getOrCreateMapping` instead. -- MIG-859 - [BREAKING] Removed method `bulkDeleteMapping` of `Migration/Mapping/MappingServiceInterface.php` and all implementors. -- MIG-859 - [BREAKING] Added default parameter `$entityValue` to `getOrCreateMapping` of `Migration/Mapping/MappingServiceInterface.php` and all implementors. Update implementors. -- MIG-859 - [BREAKING] Added default parameter `$entityValue` to `createMapping` of `Migration/Mapping/MappingServiceInterface.php` and all implementors. Update implementors. +- MIG-859 - [BREAKING] Removed method `pushMapping` of `Migration/Mapping/MappingServiceInterface.php` and all implementors. Use `getOrCreateMapping` instead +- MIG-859 - [BREAKING] Removed method `pushValueMapping` of `Migration/Mapping/MappingServiceInterface.php` and all implementors. Use `getOrCreateMapping` instead +- MIG-859 - [BREAKING] Removed method `bulkDeleteMapping` of `Migration/Mapping/MappingServiceInterface.php` and all implementors +- MIG-859 - [BREAKING] Added default parameter `$entityValue` to `getOrCreateMapping` of `Migration/Mapping/MappingServiceInterface.php` and all implementors. Update implementors +- MIG-859 - [BREAKING] Added default parameter `$entityValue` to `createMapping` of `Migration/Mapping/MappingServiceInterface.php` and all implementors. Update implementors # 5.1.2 + - MIG-871 - Fix bug for converting tax free orders - MIG-869 - Add additional information to SW6 profile page # 5.1.1 + - MIG-870 - Fix bug during migration of products # 5.1.0 + - NEXT-22545 - Add migration of digital products # 5.0.0 + - MIG-847 - Shopware 6.5 compatibility - MIG-827 - Fix migration of shipping methods with time configuration - MIG-829 - Fixed the progress bar is displayed incorrectly at a specific viewport - NTR - Migration Custom Product processing # 4.2.5 + - MIG-293 - Improve performance of order documents migration # 4.2.4 + - MIG-246 - Fix resetting of connection settings - MIG-262 - Customer migrations are no longer grouped by email address - MIG-279 - Fix pre-mapping # 4.2.3 + - MIG-269 - Fix missing order data for systems where MySQL trigger do not work # 4.2.2 + - MIG-263 - Fixes a problem, where order addresses might be erroneously identical or interchanged - MIG-260 - Fix sales channel migration with Shopware language pack # 4.2.1 + - MIG-252 - Fix profile installer view # 4.2.0 + - MIG-100 - Add migration profile for Shopware 5.7 - MIG-243 - Fix migration of orders for Shopware 6 profile - MIG-247 - Fix write protection errors for Shopware 6 migration # 4.1.1 + - MIG-206 - Migrate product creation date - MIG-237 - Fix customer vatId migration - MIG-240 - Optimize customer order count indexer # 4.1.0 + - MIG-126 - Add migration profile for Shopware 6 - MIG-221 - Fix migration of invoices - MIG-224 - Optimize attribute value migration handling from SW5 - MIG-233 - Migration of notes / wishlists added # 4.0.0 + - MIG-203 - Shopware 6.4 compatibility - MIG-220 - Optimize product image cover migration # 3.0.2 + - MIG-218 - Prevents abortion of a migration if customer has an invalid email address - MIG-219 - Solves an issue on migration translations of custom fields # 3.0.1 + - MIG-213 - Prevents abortion of a migration if some products with variants could not be written - MIG-214 - Improves progress display in CLI - MIG-216 - Fix issue with customer emails longer than 64 characters # 3.0.0 + - MIG-125 - Improves the migration of orders, that customer order count is indexed - MIG-181 - Provide migration of main variant information for Shopware 5.4 / 5.6 - MIG-182 - Migration of vouchers added @@ -339,6 +387,7 @@ - MIG-196 - Improve the extendability of the plugin # 2.2.2 + - MIG-110 - Improves the migration of media - MIG-114 - Provide migration of main variant information - MIG-118 - Fix migration of credit line items @@ -348,16 +397,19 @@ - MIG-168 - Optimized request options # 2.2.1 + - MIG-105 - Add warning if default languages differ - MIG-107 - Improves the migration of shipping methods - MIG-109 - Improve migration of orders # 2.2.0 + - MIG-75 - Improves the takeover of a migration - MIG-106 - Improves the migration of order line items - MIG-124 - Added ACL privileges # 2.1.2 + - MIG-85 - Migrate customer comments in orders - MIG-90 - Fix variant migration - MIG-92 - Fix broken history download @@ -365,16 +417,19 @@ - MIG-103 - Improves the migration of variant translations # 2.1.1 + - MIG-39 - Optimized basic converter - MIG-72 - Recognize correct category type when external link is set - MIG-73 - Recognize variant attribute translations on SW5 migration - MIG-74 - Optimize migration of custom fields # 2.1.0 + - MIG-13 - Migrate product reviews without customer - MIG-28 - Optimized rebuilding of container for deactivation and activation of the plugin # 2.0.0 + - MIG-3 - Fixes a problem with migrating order documents - MIG-5 - Improve snippet loading of DataSets - MIG-14 - Implement deletion of logs from a selected run @@ -382,59 +437,74 @@ - MIG-23 - Fixes a problem with log file download # 1.7.1 + - MIG-6 - Add functionality to save premapping without start migration for CLI support # 1.7.0 + - PT-11910 - Add migration of cross selling - PT-11922 - Shopware 6.3 compatibility - PT-11955 - Fixes a problem with saving media # 1.6.0 + - PT-11692 - Add functionality to finish migration and remove unneeded data - PT-11864 - Improve media file processing - PT-11942 - Improve migration of product-translations # 1.5.3 + - PT-11845 - Improve migration of customers - PT-11855 - Improve migration of media # 1.5.2 + - PT-11788 - Introduce migration of pseudo prices from SW5 # 1.5.1 + - PT-11819 - Optimize product variant migration for Shopware 5 profile # 1.5.0 + - PT-11692 - Move migration dashboard card to own component - PT-11747 - Ignore seo urls without type id - PT-11764 - Add sorting of pre-mapping values # 1.4.2 + - PT-11689 - Add survey to get feedback about the tool from users # 1.4.1 + - NTR - Solve issue with cache service injection # 1.4.0 + - PT-11497 - Solves an issue with incorrect connection state - PT-11601 - Shopware 6.2 compatibility - PT-11462 - Solves an issue regarding order migration # 1.3.0 + - PT-11586 - Optimized product migration from Shopware 5 - PT-11617 - Fix error with too many open database connections # 1.2.2 + - NTR - Fixes an issue with the layout when resetting the checksums # 1.2.1 + - NTR - Fixes an issue migrating media folder thumbnail settings from Shopware 5 # 1.2.0 -- PT-11450 - It is now possible to reset the checksums via a button in the connection management drop-down menu. + +- PT-11450 - It is now possible to reset the checksums via a button in the connection management drop-down menu - PT-11525 - Optimize media migration process # 1.1.0 + - PT-10832 - Preventing an undesired state when creating new connections - PT-10983 - Technical concept of the user interfaces changed to Vuex - PT-11331 - Fix request timeout for bigger migrations @@ -442,16 +512,20 @@ - PT-11400 - Migration error at wrong defined thumbnail sizes fixed # 1.0.3 + - PT-11329 - Migrate meta data for products and categories - NTR - Solves an issue with database field length difference between SW5 and SW6 # 1.0.2 + - NTR - Improve progress calculation for big amounts of data # 1.0.1 + - NTR - Solves an issue with delta checksums when aborting migration # 1.0.0 + - PT-11113 - Refactor plugin icons - PT-11111 - Refactor profile icon for external profile - NTR - Fix refresh after wizard install of external profile @@ -459,7 +533,8 @@ - PT-11252 - Force number range migration # 0.40.0 -- PT-11014- Add magento onboarding to migration wizard + +- PT-11014 - Add magento onboarding to migration wizard - PT-11016 - Refactor first migration wizard page - PT-11017 - Add migration card to dashboard - PT-11033 - Fix migration of categories @@ -472,12 +547,13 @@ - NTR - Fix product image cover when only 1 image exists # 0.30.1 + - PT-10925 - Call indexing controller after every migration - PT-10948 - Prevent duplicate document types - PT-10946 - Migrate customer language - # 0.30.0 + - PT-10629 - Raise test coverage - PT-10761 - Implement new frontend data handling - PT-10783 - Migrate empty labels with attribute name @@ -498,16 +574,20 @@ - PT-10875 - Cleanup unwritten migration data when run new starts # 0.20.0 + - Refactor imports to global object - Refactor deprecated data handling imports # 0.10.1 + - Add default theme to sales channels - Fix indexing after migration # 0.10.0 + - Implement Shopware 5.4 & Shopware 5.6 profiles - Refactor converter and reader structure # 0.9.0 + - First version of the Shopware Migration Assistant for Shopware 6 diff --git a/CHANGELOG_de-DE.md b/CHANGELOG_de-DE.md index 639bea015..20954c0f6 100644 --- a/CHANGELOG_de-DE.md +++ b/CHANGELOG_de-DE.md @@ -1,31 +1,48 @@ +# 16.0.0 + +- #13898 - Migration von Bestellungen mit unterschiedlichen Steuersätzen auf Positionen aus SW5 behoben +- #11808 - Einführung einer Benutzeroberfläche zur Fehlerbehebung, um Dateninkonsistenzen zu beheben und Migrationskorrekturen direkt in der SW6 Administration vorzunehmen, anstatt wie zuvor im Quellsystem. +- #11808 - Anreicherung der Migrations-Logs mit detaillierten Datenbeschreibungen zur besseren Nachvollziehbarkeit von Fehlern. +- #11808 - Integration von ACL-Beschränkungen zur Steuerung spezifischer Migrationsaktionen basierend auf Benutzerberechtigungen. +- #11808 - Erhöhung der Datenzuverlässigkeit durch strengere Validierungsprüfungen für konvertierte Daten. +- #11808 - Umsetzung allgemeiner UI/UX-Optimierungen für visuelle Konsistenz. +- #11808 - CLI-Befehle `migration:abort`, `migration:get-progress` und `migration:start` entfernt. Die Migration kann über die Administrations-UI gestartet werden und wird weiterhin in der Message-Queue ausgeführt. +- #11808 - Zurücksetzen der Prüfsummen und Bereinigung der Migrationsdaten erfolgen jetzt asynchron über die Message Queue. + # 15.0.3 + - Übersetzungen von Fehlergruppen behoben, welche Details wie den Entitätsnamen nicht darstellten - Fehler bei Kunden ohne Standardzahlungsmethode in SW6.7 Migrationen behoben # 15.0.2 + - Einfrieren des Browsers im Datenauswahl-Tab aufgrund einer Endlosschleife ab SW6.7RC4 behoben - Verbindungsnamen mit Bindestrichen, die Fehler bei der Migration benutzerdefinierter Felder verursachen, wurden behoben - Behebt einen Fehler im Premapping für Administrations-Benutzer, wenn der Benutzername leer ist # 15.0.1 + - Deprecation-Warnungen für das tagged-Argument in Service-Definitionen behoben # 15.0.0 + - MIG-1094 - Kompatibilität mit Shopware Version 6.7 hinzugefügt # 14.1.0 + - MIG-1082 - Behebt einen Fehler bei wiederholender Migration von Kundenwunschlisten von SW5 nach SW6 - MIG-1096 - Beseitigt `json_decode` mit `null` Run Exceptions, die bei Mappings von alten Migrationsläufen auftraten (ältere Assistant-Versionen) # 14.0.0 + - Technische Änderungen und Breaking-Changes wurden nach https://github.com/shopware/SwagMigrationAssistant/blob/trunk/UPGRADE.md umgezogen -- MIG-894 - Verbessert die Mapping Performance der Migration, was zu einem deutlich schnelleren Konvertierungsvorgang führt. +- MIG-894 - Verbessert die Mapping Performance der Migration, was zu einem deutlich schnelleren Konvertierungsvorgang führt - MIG-1033 - Die Migration der SEO-Hauptkategorie für Produkte mit SW5 oder SW6 als Quellsystem wurde hinzugefügt - MIG-1039 - Für Kunden- und Bestelladressen werden jetzt auch die Bundesländer migriert - MIG-1050 - Optimiert die Migration von SEO-URLs -- MIG-1052 - Die Migration der „Von Admin erstellt“-Flags bei Kunden und Bestellungen wurde behoben +- MIG-1052 - Die Migration der „Von Admin erstellt"-Flags bei Kunden und Bestellungen wurde behoben - MIG-1052 - Premapping für Administrations-Benutzer mit automatischer Vorauswahl hinzugefügt, wenn der Benutzername identisch ist -- MIG-1053 - Die EnvironmentReader-Klassen von Shopware 5 und Shopware 6 wurden überarbeitet, um mehr Informationen zu Ausnahmen bereitzustellen. +- MIG-1053 - Die EnvironmentReader-Klassen von Shopware 5 und Shopware 6 wurden überarbeitet, um mehr Informationen zu Ausnahmen bereitzustellen - MIG-1054 - Fehler bei Migration von Bestellungen aus SW5.4 behoben - MIG-1061 - Die Migration von Wunschlisten von SW6 nach SW6 mit einer leeren Produkt-Liste wurde behoben - MIG-1062 - Die Migration von Produktbewertungen von SW6 nach SW6 mit fehlenden zugehörigen Kunden wurde behoben @@ -38,18 +55,21 @@ - MIG-1087 - Es wurde ein Problem bei der Migration von Medienordnern von SW6->SW6 behoben, bei dem die Standardordner-ID falsch gesetzt war. Dies beinhaltet Änderungen an der Art und Weise, wie die Ordnerstruktur migriert wird # 13.2.0 + - MIG-1035 - Die Premapping-Zuweisung im Admin wurde geändert, wodurch Probleme mit der Zuweisung auf späteren Paginierungsseiten und dem Verlust von Änderungen bei neu ausgewählten Daten behoben sein sollten -- MIG-1042 - Fügt einen Hinweises bezüglich des Löschen des Caches hinzu, wenn der Shopware 5 Connector nicht erkannt wird. +- MIG-1042 - Fügt einen Hinweis bezüglich des Löschens des Caches hinzu, wenn der Shopware 5 Connector nicht erkannt wird - MIG-1045 - Korrigiert den angezeigten prozentualen Status beim Lesen von Daten - MIG-1046 - Behebung eines Problems bei der Validierung von json-Feldern für einen Migrationslauf, das den Start einer Migration in der neuesten Shopware-Version verhindern konnte # 13.1.0 -- MIG-981 - Die Medienmigration verwendet jetzt das temporäre Verzeichnis des Systems zum Herunterladen von Dateien. -- MIG-1016 - Verbessert die Warnungen für unterschiedliche Standardwährung und Standardsprache in der Datenauswahl. -- MIG-1016 - Fügt einen neuen Block `{% block swag_migration_confirm_warning_alert %}` in `swag-migration/component/card/swag-migration-confirm-warning/swag-migration-confirm-warning.html.twig` hinzu. -- MIG-1037 - Behebt ein seltenes Problem, dass in bestimmten Situationen nicht alle Entitäten migriert werden (bzw. einige übersprungen werden). Wurde bei Übersetzungen von SW5 festgestellt. + +- MIG-981 - Die Medienmigration verwendet jetzt das temporäre Verzeichnis des Systems zum Herunterladen von Dateien +- MIG-1016 - Verbessert die Warnungen für unterschiedliche Standardwährung und Standardsprache in der Datenauswahl +- MIG-1016 - Fügt einen neuen Block `{% block swag_migration_confirm_warning_alert %}` in `swag-migration/component/card/swag-migration-confirm-warning/swag-migration-confirm-warning.html.twig` hinzu +- MIG-1037 - Behebt ein seltenes Problem, dass in bestimmten Situationen nicht alle Entitäten migriert werden (bzw. einige übersprungen werden). Wurde bei Übersetzungen von SW5 festgestellt # 13.0.0 + - MIG-945 - [BREAKING] Änderung des Methodennamens `getMedia` zu `setMedia` in `SwagMigrationAssistant\Profile\Shopware\Converter\PropertyGroupOptionConverter` - MIG-945 - [BREAKING] CLI-Befehl `migration:migrate` entfernt und verwende stattdessen `migration:start` - MIG-945 - [BREAKING] Geänderte Methode `writePremapping` von `SwagMigrationAssistant\Controller\PremappingController` @@ -124,10 +144,11 @@ - MIG-1011 - Sicherstellung, dass Datenbankattribute (wie z. B. "stringify fetches") bei lokalen Gateway-Verbindungen immer gesetzt sind # 12.0.0 + - MIG-983 - Korrigiert einen Fehler bei der Migration von Kunden, die an einen Shop gebunden sind -- MIG-983 - [BREAKING] In der Klasse `\SwagMigrationAssistant\Profile\Shopware\Converter\OrderConverter` wurde der Methodenname `getAddresses` in `applyAddresses` geändert. -- MIG-983 - [BREAKING] In der Klasse `\SwagMigrationAssistant\Profile\Shopware\Converter\OrderConverter` wurde der Methodenname `getCountryTranslation` in `applyCountryTranslation` geändert. -- MIG-983 - [BREAKING] In der Klasse `\SwagMigrationAssistant\Profile\Shopware\Converter\OrderConverter` wurde der Methodenname `getCountryStateTranslation` in `applyCountryStateTranslation` geändert. +- MIG-983 - [BREAKING] In der Klasse `\SwagMigrationAssistant\Profile\Shopware\Converter\OrderConverter` wurde der Methodenname `getAddresses` in `applyAddresses` geändert +- MIG-983 - [BREAKING] In der Klasse `\SwagMigrationAssistant\Profile\Shopware\Converter\OrderConverter` wurde der Methodenname `getCountryTranslation` in `applyCountryTranslation` geändert +- MIG-983 - [BREAKING] In der Klasse `\SwagMigrationAssistant\Profile\Shopware\Converter\OrderConverter` wurde der Methodenname `getCountryStateTranslation` in `applyCountryStateTranslation` geändert - MIG-986 - Behebt einen Fehler bei der Migration von Trackingnummern in den Bestellungen - MIG-989 - Verbesserung der Migration von Mediendateien - MIG-989 - [BREAKING] Neue Methode `filterUnwrittenData` zu `SwagMigrationAssistant\Migration\Media\MediaFileServiceInterface` hinzugefügt @@ -139,10 +160,12 @@ - MIG-1006 - Behebt einen Fehler bei der Migration von Produkt-Coverbildern # 11.0.1 -- MIG-988 - Ein Fehler der Premapping-UI wurde behoben, um kompatible mit der neusten Platform version zu bleiben + +- MIG-988 - Ein Fehler der Premapping-UI wurde behoben, um kompatibel mit der neuesten Platform-Version zu bleiben # 11.0.0 -- MIG-951 - Verbessert die Sprachmigration von Shopware 6 zu Shopware 6, damit die Standardsprache nicht mehr überschrieben wird. + +- MIG-951 - Verbessert die Sprachmigration von Shopware 6 zu Shopware 6, damit die Standardsprache nicht mehr überschrieben wird - MIG-951 - [BREAKING] Ändert den Zugriffsmodifikator der Funktion `\SwagMigrationAssistant\Profile\Shopware6\Converter\LanguageConverter::convertData` von public auf protected - MIG-943 - Korrigiert einen Fehler in der Migration der Versandkostenberechnung von Shopware 5 - MIG-943 - [BREAKING] In der Klasse `\SwagMigrationAssistant\Profile\Shopware\Converter\OrderConverter` wurde der Methodenname `getTransactions` in `applyTransactions` geändert @@ -152,20 +175,23 @@ - MIG-967, MIG-866 - Verbesserung der Migration von Bestell-Dokumenten # 10.0.1 + - MIG-971 - Korrigiert Kompatibilität mit Shopware 6.6.0.x # 10.0.0 -- NEXT-34526 - [BREAKING] Der Parameter `result` der Methode `SwagMigrationAssistant\DataProvider\Provider\Data\AbstractProvider::cleanupSearchResult` wurde um den nativen Typ erweitert. -- NEXT-34526 - [BREAKING] Die Datei `DataProvider/Exception/ProviderHasNoTableAccessException.php` wurde entfernt, stattdessen `SwagMigrationAssistant\Exception\MigrationException::providerHasNoTableAccess` verwenden. -- NEXT-34526 - [BREAKING] Die Datei `Profile/Shopware/Exception/ParentEntityForChildNotFoundException.php` wurde entfernt, stattdessen `SwagMigrationAssistant\Exception\MigrationException::parentEntityForChildNotFound` verwenden. -- NEXT-34526 - [BREAKING] In der Klasse `SwagMigrationAssistant\Profile\Shopware\Converter\CategoryConverter` wurde der Methodenname `getMediaTranslation` in `addMediaTranslation` geändert. -- NEXT-34526 - [BREAKING] In der Klasse `SwagMigrationAssistant\Profile\Shopware\Converter\TranslationConverter` wurde der Methodenname `getAttribute` in `addAttribute` geändert. -- NEXT-34526 - [BREAKING] Der Parametername `blacklist` wurde in `excludeList` in der Methode `SwagMigrationAssistant\Profile\Shopware\Converter\ShopwareConverter::getAttributes` geändert. + +- NEXT-34526 - [BREAKING] Der Parameter `result` der Methode `SwagMigrationAssistant\DataProvider\Provider\Data\AbstractProvider::cleanupSearchResult` wurde um den nativen Typ erweitert +- NEXT-34526 - [BREAKING] Die Datei `DataProvider/Exception/ProviderHasNoTableAccessException.php` wurde entfernt, stattdessen `SwagMigrationAssistant\Exception\MigrationException::providerHasNoTableAccess` verwenden +- NEXT-34526 - [BREAKING] Die Datei `Profile/Shopware/Exception/ParentEntityForChildNotFoundException.php` wurde entfernt, stattdessen `SwagMigrationAssistant\Exception\MigrationException::parentEntityForChildNotFound` verwenden +- NEXT-34526 - [BREAKING] In der Klasse `SwagMigrationAssistant\Profile\Shopware\Converter\CategoryConverter` wurde der Methodenname `getMediaTranslation` in `addMediaTranslation` geändert +- NEXT-34526 - [BREAKING] In der Klasse `SwagMigrationAssistant\Profile\Shopware\Converter\TranslationConverter` wurde der Methodenname `getAttribute` in `addAttribute` geändert +- NEXT-34526 - [BREAKING] Der Parametername `blacklist` wurde in `excludeList` in der Methode `SwagMigrationAssistant\Profile\Shopware\Converter\ShopwareConverter::getAttributes` geändert - MIG-868 - Verbesserung der Produkt-Migration, der Brutto-Einkaufspreis wird jetzt berechnet -- MIG-966 - [BREAKING] Die Quelldateien wurden in das `src`-Verzeichnis verschoben und das `Test`-Verzeichnis in `tests` umbenannt, ohne Namespaces zu brechen, jedoch muss das Plugin evtl. neu aktiviert bzw. installiert werden. Damit wurde ein Fehler in unserem Deployment-Prozess behoben, um das Plugin korrekt zu bauen. -- MIG-930 - Verbesserung der Cross-Selling-Migration, das Cross-Selling überschreibt nicht mehr das bestehende Cross-Selling, wenn es keine Änderungen gibt. +- MIG-966 - [BREAKING] Die Quelldateien wurden in das `src`-Verzeichnis verschoben und das `Test`-Verzeichnis in `tests` umbenannt, ohne Namespaces zu brechen, jedoch muss das Plugin evtl. neu aktiviert bzw. installiert werden. Damit wurde ein Fehler in unserem Deployment-Prozess behoben, um das Plugin korrekt zu bauen +- MIG-930 - Verbesserung der Cross-Selling-Migration, das Cross-Selling überschreibt nicht mehr das bestehende Cross-Selling, wenn es keine Änderungen gibt # 9.0.0 + - MIG-848 - Verbesserung der Zuordnung von Produkten zu Verkaufskanälen über Sub- und Sprachshops - MIG-920 - Unterstützte Shopware 6 Version auf 6.6 geändert und Anpassungen an den Profilen vorgenommen - MIG-920 - `Migration/Gateway/HttpClientInterface` hinzugefügt, um die Verwendung von HTTP-Clients zu vereinheitlichen @@ -181,20 +207,21 @@ - MIG-920 - `Migration/Media/Processor/HttpDownloadServiceBase.php` hinzugefügt, um das Herunterladen von Mediendateien zu vereinheitlichen - MIG-920 - [BREAKING] Übergeordnete Klasse und Implementierung von `Profile/Shopware/Media/HttpMediaDownloadService.php` zu `Migration/Media/Processor/HttpDownloadServiceBase.php` geändert - MIG-920 - [BREAKING] Übergeordnete Klasse und Implementierung von `Profile/Shopware/Media/HttpOrderDocumentProcessor.php` zu `Migration/Media/Processor/HttpDownloadServiceBase.php` geändert -- MIG-920 - [BREAKING] Umbenennung von `Profile/Shopware/Media/HttpOrderDocumentProcessor.php` in `Profile/Shopware/Media/HttpOrderDocumentDownloadService.php`. +- MIG-920 - [BREAKING] Umbenennung von `Profile/Shopware/Media/HttpOrderDocumentProcessor.php` in `Profile/Shopware/Media/HttpOrderDocumentDownloadService.php` - MIG-920 - [BREAKING] Übergeordnete Klasse und Implementierung von `Profile/Shopware/Media/HttpProductDownloadProcessor.php` in `Migration/Media/Processor/HttpDownloadServiceBase.php` geändert - MIG-920 - [BREAKING] Umbenennung von `Profile/Shopware/Media/HttpProductDownloadProcessor.php` in `Profile/Shopware/Media/HttpEsdFileDownloadService.php` - MIG-920 - [BREAKING] Übergeordnete Klasse und Implementierung von `Profile/Shopware6/Media/HttpMediaDownloadService.php` zu `Migration/Media/Processor/HttpDownloadServiceBase.php` geändert -- MIG-920 - [BREAKING] Geänderte übergeordnete Klasse und Implementierung von `Profile/Shopware6/Media/HttpOrderDocumentService.php` zu `Migration/Media/Processor/HttpDownloadServiceBase.php`. +- MIG-920 - [BREAKING] Geänderte übergeordnete Klasse und Implementierung von `Profile/Shopware6/Media/HttpOrderDocumentService.php` zu `Migration/Media/Processor/HttpDownloadServiceBase.php` - MIG-920 - [BREAKING] Umbenennung von `Profile/Shopware6/Media/HttpOrderDocumentService.php` in `Profile/Shopware/Media/HttpOrderDocumentDownloadService.php` - MIG-934 - Neue Route `/api/_action/data-provider/download-private-file/{file}` zum Abrufen digitaler Produktdateien hinzugefügt - MIG-934 - Die Datei `DataProvider/Provider/Data/ProductProvider.php` wurde geändert, um Download-Medien für digitale Produkte einzubeziehen - MIG-934 - Die Datei `Profile/Shopware6/Converter/ProductConverter.php` wurde geändert, um Download-Medien für digitale Produkte einzubeziehen - MIG-934 - Datei `Profile/Shopware6/DataSelection/DataSet/ProductDownloadDataSet.php` hinzugefügt - MIG-934 - Datei `Profile/Shopware6/Media/HttpProductDownloadService.php` hinzugefügt -- MIG-934 - [BREAKING] Die Datei `Controller/DataProviderController.php` wurde in final geändert. +- MIG-934 - [BREAKING] Die Datei `Controller/DataProviderController.php` wurde in final geändert # 8.0.0 + - MIG-274 - Behebt einen Fehler in der Migration von Cross-Selling Produkten - MIG-825 - Verbesserung der Performance bei der Migration von Bestellungen - MIG-825 - Hinzufügen der Optionen `step-size` zum Cli-Befehl `migration:migrate` von `Command/MigrationCommand.php` @@ -226,109 +253,130 @@ - MIG-938 - Behebt Berechnungsfehler bei der Migration von Versandkostenpreisen # 7.0.2 + - MIG-908 - Behebung der Shopware 6 Migration von `system_config` Entitäten, die nicht zwischen verschiedenen Shops migriert werden sollten # 7.0.1 + - MIG-907 - Shopware 6 Profilenamen in Verbindungen korrigiert # 7.0.0 + - NEXT-31367 - Verbesserung der ConnectionFactory, damit sie stabiler funktioniert -- MIG-881 - Behebt einen Fehler bei der Konvertierung von Versandarten und Versandkosten und migriert auch Versandarten mit unbekanntem Berechnungstyp. -- MIG-878 - Korrektur der Migration von SW6.5 zu SW6.5. Nur gleiche Major-Versionen werden unterstützt. -- MIG-905 - Hotfix / bekanntes Problem für SW6->SW6: `canonicalProductId` von `product` wird nicht migriert, verhindert aber vorerst nicht die Migration von Produkten. -- MIG-905 - Hotfix / bekanntes Problem für SW6->SW6: `cmsPageId` von `product` wird nicht migriert, verhindert aber vorerst nicht die Migration von Produkten. -- MIG-905 - Hotfix / bekanntes Problem für SW6->SW6: `promotionId` von Einzelposten einer Bestellung wird nicht migriert, verhindert aber nicht die Migration von Bestellungen. -- MIG-881 - [BREAKING] Methode `getDefaultAvailabilityRule` vom `Migration/Mapping/MappingServiceInterface.php` wurde entfernt und alle Implementierung angepasst. Nutze stattdessen das Premapping von `default_shipping_availability_rule`. -- MIG-881 - [BREAKING] Parameter `customerRepository` von `Migration/MessageQueue/OrderCountIndexer.php` wurde entfernt. +- MIG-881 - Behebt einen Fehler bei der Konvertierung von Versandarten und Versandkosten und migriert auch Versandarten mit unbekanntem Berechnungstyp +- MIG-878 - Korrektur der Migration von SW6.5 zu SW6.5. Nur gleiche Major-Versionen werden unterstützt +- MIG-905 - Hotfix / bekanntes Problem für SW6->SW6: `canonicalProductId` von `product` wird nicht migriert, verhindert aber vorerst nicht die Migration von Produkten +- MIG-905 - Hotfix / bekanntes Problem für SW6->SW6: `cmsPageId` von `product` wird nicht migriert, verhindert aber vorerst nicht die Migration von Produkten +- MIG-905 - Hotfix / bekanntes Problem für SW6->SW6: `promotionId` von Einzelposten einer Bestellung wird nicht migriert, verhindert aber nicht die Migration von Bestellungen +- MIG-881 - [BREAKING] Methode `getDefaultAvailabilityRule` vom `Migration/Mapping/MappingServiceInterface.php` wurde entfernt und alle Implementierung angepasst. Nutze stattdessen das Premapping von `default_shipping_availability_rule` +- MIG-881 - [BREAKING] Parameter `customerRepository` von `Migration/MessageQueue/OrderCountIndexer.php` wurde entfernt - MIG-878 - [BREAKING] Alle Klassen unter `Profile/Shopware63` wurden entfernt. Verwenden Sie stattdessen die Klassen unter `Profile/Shopware6`. - MIG-878 - [BREAKING] Alle Konverter unter `Profile/Shopware6/Converter` wurden so geändert, dass sie nicht `abstrakt` sind und die entsprechenden `supports` Methoden implementieren. Diese ersetzen nun die alten Konverter unter `Profile/Shopware63/Converter`. -- MIG-878 - [BREAKING] Umbenennung von `Profile/Shopware63/Shopware63Profile.php` in `Profile/Shopware6/Shopware6MajorProfile`. -- MIG-878 - [BREAKING] `Profile/Shopware6/Shopware6MajorProfile` wurde geändert, um nur noch die aktuelle SW6 Major-Version zu unterstützen. -- MIG-878 - [BREAKING] `Profile/Shopware6/Shopware6MajorProfile` liefert nun `shopware6major` bei `getName`. -- MIG-878 - [BREAKING] Umbenennung der Vue-Komponente `swag-migration-profile-shopware6-api-credential-form` in `swag-migration-profile-shopware6major-api-credential-form`. -- MIG-878 - [BREAKING] Umbenennung der Vue-Komponente `swag-migration-profile-shopware6-api-page-information` in `swag-migration-profile-shopware6major-api-page-information`. -- MIG-878 - [BREAKING] Die Vue-Komponente `swag-migrationsprofil-shopware63-api-credential-form` wurde entfernt. -- MIG-878 - [BREAKING] Die Vue-Komponente `swag-migration-profile-shopware63-api-page-information` wurde entfernt. -- MIG-878 - [BREAKING] Die Datei `Profile/Shopware6/DataSelection/DataSet/ProductMainVariantRelationDataSet.php` wurde entfernt, da sie bereits mit der Entität `Product` in SW6 migriert wurde. -- MIG-878 - [BREAKING] Die Datei `DataProvider/Provider/Data/ProductMainVariantRelationProvider.php` wurde entfernt, da sie bereits mit der Entität `Product` in SW6 migriert wurde. -- MIG-878 - [BREAKING] Die Datei `Profile/Shopware6/Gateway/Api/Reader/ProductMainVariantRelationReader.php` wurde entfernt, da sie bereits mit der Entität `Product` in SW6 migriert wurde. -- MIG-878 - [BREAKING] Die Datei `Profile/Shopware6/Converter/ProductMainVariantRelationConverter.php` wurde entfernt, da sie bereits mit der Entität `Product` in SW6 migriert wurde. +- MIG-878 - [BREAKING] Umbenennung von `Profile/Shopware63/Shopware63Profile.php` in `Profile/Shopware6/Shopware6MajorProfile` +- MIG-878 - [BREAKING] `Profile/Shopware6/Shopware6MajorProfile` wurde geändert, um nur noch die aktuelle SW6 Major-Version zu unterstützen +- MIG-878 - [BREAKING] `Profile/Shopware6/Shopware6MajorProfile` liefert nun `shopware6major` bei `getName` +- MIG-878 - [BREAKING] Umbenennung der Vue-Komponente `swag-migration-profile-shopware6-api-credential-form` in `swag-migration-profile-shopware6major-api-credential-form` +- MIG-878 - [BREAKING] Umbenennung der Vue-Komponente `swag-migration-profile-shopware6-api-page-information` in `swag-migration-profile-shopware6major-api-page-information` +- MIG-878 - [BREAKING] Die Vue-Komponente `swag-migrationsprofil-shopware63-api-credential-form` wurde entfernt +- MIG-878 - [BREAKING] Die Vue-Komponente `swag-migration-profile-shopware63-api-page-information` wurde entfernt +- MIG-878 - [BREAKING] Die Datei `Profile/Shopware6/DataSelection/DataSet/ProductMainVariantRelationDataSet.php` wurde entfernt, da sie bereits mit der Entität `Product` in SW6 migriert wurde +- MIG-878 - [BREAKING] Die Datei `DataProvider/Provider/Data/ProductMainVariantRelationProvider.php` wurde entfernt, da sie bereits mit der Entität `Product` in SW6 migriert wurde +- MIG-878 - [BREAKING] Die Datei `Profile/Shopware6/Gateway/Api/Reader/ProductMainVariantRelationReader.php` wurde entfernt, da sie bereits mit der Entität `Product` in SW6 migriert wurde +- MIG-878 - [BREAKING] Die Datei `Profile/Shopware6/Converter/ProductMainVariantRelationConverter.php` wurde entfernt, da sie bereits mit der Entität `Product` in SW6 migriert wurde # 6.0.1 + - MIG-887 - Verbesserung der Performance des Endpunktes, welcher alle Daten erfasst, die anschließend geschrieben werden sollen # 6.0.0 + - MIG-879 - Fehler beim Migrieren von steuerfreien Bestellungen aus SW5 behoben -- MIG-859 - [BREAKING] Methode `pushMapping` vom `Migration/Mapping/MappingServiceInterface.php` wurde entfernt und alle Implementierung angepasst. Nutze stattdessen `getOrCreateMapping`. -- MIG-859 - [BREAKING] Methode `pushValueMapping` vom `Migration/Mapping/MappingServiceInterface.php` wurde entfernt und alle Implementierung angepasst. Nutze stattdessen `getOrCreateMapping`. -- MIG-859 - [BREAKING] Methode `bulkDeleteMapping` vom `Migration/Mapping/MappingServiceInterface.php` wurde entfernt und alle Implementierung angepasst. -- MIG-859 - [BREAKING] Default Parameter `$entityValue` zu `getOrCreateMapping` vom `Migration/Mapping/MappingServiceInterface.php` hinzugefügt und alle Implementierungen angepasst. Passe Implementierungen an. -- MIG-859 - [BREAKING] Default Parameter `$entityValue` zu `createMapping` vom `Migration/Mapping/MappingServiceInterface.php` hinzugefügt und alle Implementierungen angepasst. Passe Implementierungen an. +- MIG-859 - [BREAKING] Methode `pushMapping` vom `Migration/Mapping/MappingServiceInterface.php` wurde entfernt und alle Implementierung angepasst. Nutze stattdessen `getOrCreateMapping` +- MIG-859 - [BREAKING] Methode `pushValueMapping` vom `Migration/Mapping/MappingServiceInterface.php` wurde entfernt und alle Implementierung angepasst. Nutze stattdessen `getOrCreateMapping` +- MIG-859 - [BREAKING] Methode `bulkDeleteMapping` vom `Migration/Mapping/MappingServiceInterface.php` wurde entfernt und alle Implementierung angepasst +- MIG-859 - [BREAKING] Default Parameter `$entityValue` zu `getOrCreateMapping` vom `Migration/Mapping/MappingServiceInterface.php` hinzugefügt und alle Implementierungen angepasst. Passe Implementierungen an +- MIG-859 - [BREAKING] Default Parameter `$entityValue` zu `createMapping` vom `Migration/Mapping/MappingServiceInterface.php` hinzugefügt und alle Implementierungen angepasst. Passe Implementierungen an # 5.1.2 + - MIG-871 - Fehler beim Migrieren von steuerfreien Bestellungen behoben - MIG-869 - Zusätzliche Informationen zur SW6 Profilseite hinzugefügt # 5.1.1 + - MIG-870 - Fehler bei der Produktmigration behoben # 5.1.0 + - NEXT-22545 - Migration von digitalen Produkten hinzugefügt # 5.0.0 + - MIG-847 - Kompatibilität für Shopware 6.5 - MIG-827 - Migration von Versandarten mit Zeitkonfiguration behoben - MIG-829 - Fortschrittsbalken, der in einem bestimmten Ansichtsfenster falsch angezeigt wird, ist behoben - NTR - Migration von Custom Products # 4.2.5 + - MIG-293 - Performance der Migration von Bestelldokumenten verbessert # 4.2.4 + - MIG-246 - Zurücksetzen der Verbindungseinstellungen korrigiert - MIG-262 - Kundenmigrationen werden nicht mehr nach E-Mail-Adressen gruppiert - MIG-279 - Vorabzuordnung korrigiert # 4.2.3 + - MIG-269 - Fehlende Daten in der Bestellung korrigiert, für Systeme auf denen MySQL-Trigger nicht funktionieren # 4.2.2 + - MIG-263 - Behebt ein Problem, bei dem Bestelladressen fälschlicherweise identisch oder vertauscht sein konnten - MIG-260 - Behebt ein Problem bei der Migration von Verkaufskanälen mit dem Shopware-Sprachpacket # 4.2.1 + - MIG-252 - Behebt ein Problem auf der Profil-Installationsseite # 4.2.0 + - MIG-100 - Migrationsprofil für Shopware 5.7 hinzugefügt - MIG-243 - Behebt ein Problem bei der Migration von Bestellungen mit dem Shopware-6-Profil - MIG-247 - Behebt ein Problem mit Schreibschutz-Fehlern bei Shopware-6-Migrationen # 4.1.1 + - MIG-206 - Migration des Erstelldatums der Produkte - MIG-237 - Behebt ein Problem bei der Migration der UStId - MIG-240 - Optimiert den Customer Indexer zum Zählen der Bestellungen # 4.1.0 + - MIG-126 - Migrationsprofil für Shopware 6 hinzugefügt - MIG-221 - Behebt die Migration von Rechnungen - MIG-224 - Optimierung der Attributwertmigration aus SW5 - MIG-233 - Migration der Merkzettel / Wunschlisten hinzugefügt # 4.0.0 + - MIG-203 - Kompatibilität für Shopware 6.4 - MIG-220 - Optimiert die Migration von Produkt-Vorschaubildern # 3.0.2 + - MIG-218 - Verhindert den Abbruch der Migration, wenn ein Kunde eine ungültige E-Mail-Adresse hat - MIG-219 - Behebt ein Problem bei der Migration von Übersetzungen der Freitextfelder # 3.0.1 + - MIG-213 - Verhindert den Abbruch der Migration beim Schreiben von fehlerhaften Produktvarianten - MIG-214 - Verbessert die Fortschrittsdarstellung in der CLI - MIG-216 - Behebt ein Problem mit Kunden-E-Mail-Adressen, die länger als 64 Zeichen sind # 3.0.0 + - MIG-125 - Verbessert die Migration von Bestellungen, sodass die Anzahl der Kundenbestellungen indexiert wird - MIG-181 - Migration der Hauptvarianten-Informationen ermöglichen für Shopware 5.4 / 5.6 - MIG-182 - Migration der Gutscheine hinzugefügt @@ -339,25 +387,29 @@ - MIG-196 - Verbessert die Erweiterbarkeit des Plugins # 2.2.2 + - MIG-110 - Verbessert die Migration der Medien - MIG-114 - Migration der Hauptvarianten-Information ermöglichen - MIG-118 - Korrigiert die Migration der Kredit-Bestellpositionen - MIG-120 - Behebt ein Problem beim Laden des Premappings -- MIG-162 - Behebt ein Problem bei der Migration von Produkten mit leeren Freitextfeldern +- MIG-162 - Behebt ein Problem bei der Migration von Produkten mit leeren Freitextfeldern - MIG-167 - Behebt ein Problem bei der Migration von Freitextfeldwerten - MIG-168 - Optimiertes Request Handling # 2.2.1 + - MIG-105 - Warnung hinzufügen, wenn sich die Standardsprachen unterscheiden - MIG-107 - Verbessert die Migration von Versandarten - MIG-109 - Verbessern der Migration der Bestellungen # 2.2.0 + - MIG-75 - Verbessert das Übernehmen einer Migration - MIG-106 - Verbessert die Migration von Bestellpositionen - MIG-124 - ACL-Privilegien hinzugefügt # 2.1.2 + - MIG-85 - Berücksichtigt die Kundenkommentare bei Bestellungen - MIG-90 - Behebt einen Fehler bei der Variantenmigration - MIG-92 - Behebt ein Problem beim Download der Historie @@ -365,16 +417,19 @@ - MIG-103 - Verbessert die Migration von Variantenübersetzungen # 2.1.1 + - MIG-39 - Optimierung im Basiskonverter - MIG-72 - Berücksichtigt korrekten Kategorietypen wenn es einen externen Link gibt - MIG-73 - Berücksichtigt die Attributübersetzungen bei Variantenartikeln von SW5 - MIG-74 - Optimierte Attributmigration von Shopware 5 # 2.1.0 + - MIG-13 - Migration von Produktbewertungen ohne Kunden ermöglichen - MIG-28 - Optmierte Neugenerierung des Containers bei Aktivierung und Deaktivierung # 2.0.0 + - MIG-3 - Korrigiert ein Problem bei der Migration von Bestelldokumenten - MIG-5 - Verbessertes Laden von Snippets der DataSets - MIG-14 - Löschen des Protokolls eines Durchlaufes ist jetzt in der Historie möglich @@ -382,59 +437,74 @@ - MIG-23 - Korrigiert ein Problem beim Herunterladen der Logdatei # 1.7.1 + - MIG-6 - Neue Funktion zum Speichern des Premappings ohne das Starten einer Migration für den CLI-Support # 1.7.0 + - PT-11910 - Migration von CrossSelling hinzugefügt - PT-11922 - Kompatibilität für Shopware 6.3 - PT-11955 - Behebt ein Problem beim Speichern der Medien # 1.6.0 + - PT-11692 - Neue Funktion zum Abschluss des Migrationsprozesses die nicht mehr benötigte Daten entfernt - PT-11864 - Verarbeitung der Medien verbessert - PT-11942 - Verbessern der Migration von Produkt-Übersetzungen # 1.5.3 + - PT-11845 - Verbessern der Migration von Kunden - PT-11855 - Verbessern der Migration von Medien # 1.5.2 + - PT-11788 - Migration von Pseudo-Preisen aus SW5 integriert # 1.5.1 + - PT-11819 - Optimiert die Produkt-Varianten Migration für das Shopware 5 Profil # 1.5.0 + - PT-11692 - Dashboard-Karte des Migrations-Assistenten ist nun eigene Komponente - PT-11747 - Behebt ein Problem, wenn SEO urls keine Typ Id haben - PT-11764 - Werte im Datencheck werden jetzt sortiert ausgegeben # 1.4.2 + - PT-11689 - Fügt einen Umfrage-Link zur Qualität des Produktes hinzu # 1.4.1 + - NTR - Behebt ein Problem beim Injekten des Cache-Services # 1.4.0 + - PT-11497 - Behebt ein Problem mit falschem Verbindungsstatus - PT-11601 - Shopware 6.2 Kompatibilität - PT-11462 - Behebt ein Problem bei der Migration von Bestellungen # 1.3.0 + - PT-11586 - Optimierte Produktmigration von Shopware 5 - PT-11617 - Behebt ein Problem mit zu vielen offenen Datenbankverbindungen per CLI # 1.2.2 + - NTR - Behebt ein Problem mit dem Layout beim Zurücksetzen der Checksummen # 1.2.1 + - NTR - Behebt ein Problem bei der Migration der Medienordner-Einstellungen aus Shopware 5 # 1.2.0 + - PT-11450 - Es ist jetzt möglich die Prüfsummen über einen Button im Dropdown für die Verbindungsverwaltung zurückzusetzen. - PT-11525 - Optimiert den Migrationsprozess für Medien # 1.1.0 + - PT-10832 - Verhindern eines unerwünschten Zustands beim Anlegen neuer Verbindungen - PT-10983 - Technisches Konzept der Oberflächen auf Vuex geändert - PT-11331 - Zeitüberschreitung bei Anfragen für größere Migrationen behoben @@ -442,23 +512,28 @@ - PT-11400 - Migrationsfehler bei falsch definierten Thumbnail Größen behoben # 1.0.3 + - PT-11329 - Metadaten für Produkte und Kategorien migrieren - NTR - Behebt ein Problem mit Differenz der Datenbank Feldlänge zwischen SW5 und SW6 # 1.0.2 + - NTR - Verbessert die Performanz beim Berechnen des Fortschritts # 1.0.1 + - NTR - Behebt ein Problem mit den Checksummen der Delta-Migration beim Abbruch der Migration # 1.0.0 + - PT-11113 - Anpassung der Plugin icons - PT-11111 - Anpassung des Profilicons für externe Profile -- NTR - Behebt ein Problem nach dem Installieren von extern Profilen +- NTR - Behebt ein Problem nach dem Installieren von extern Profilen - NTR - Snippet renaming - PT-11252 - Nummernkreise werden jetzt in den Basisdaten migriert # 0.40.0 + - PT-11014- Magento-Onboarding zum Migration-Wizard hinzufügen - PT-11016 - Anpassen der ersten Migration-Wizard-Seite - PT-11017 - Hinzufügen einer Migration-Card zum Dashboard @@ -472,11 +547,13 @@ - NTR - Fixen des Produktcovers bei nur einem Produktbild # 0.30.1 + - PT-10925 - Indexing-Controller nach jeder Migration aufrufen - PT-10948 - Doppelte Dokumententypen verhindern - PT-10946 - Migrieren der Kundensprache # 0.30.0 + - PT-10629 - Erhöhung der Testabdeckung - PT-10761 - Neues Frontend data handling - PT-10783 - Migration von Attributen ohne Label optimiert @@ -497,16 +574,20 @@ - PT-10875 - Cleanup der nicht geschriebenen Migrationsdaten wenn ein neuer Run startet # 0.20.0 + - Refaktorierung von imports zu global object - Refaktorierung von abgelaufenen data handling Importen # 0.10.1 + - Standard-Theme zu den Verkaufskanälen hinzugefügt - Indexierung nach der Migration verbessert # 0.10.0 + - Shopware 5.4 & Shopware 5.6 Profile implementiert - Converter- und Reader-Struktur überarbeitet # 0.9.0 + - Erste Version des Shopware Migrationassistent für Shopware 6 diff --git a/README.md b/README.md index 616dfb180..1c7d81c86 100644 --- a/README.md +++ b/README.md @@ -1,45 +1,127 @@ -# Shopware Migration Assistant (SwagMigrationAssistant) +# SwagMigrationAssistant -## License +The Shopware Migration Assistant establishes a connection between a data source and Shopware 6 and guides you step by step through the migration process. -The MIT License (MIT). Please see [License File](LICENSE) for more information. +It supports migrating numerous datasets (products, manufacturers, customers, …) and updating them at any time. Before a migration starts, the assistant runs a data check and supports creating “mappings” to resolve missing/unassignable data (for example: assign missing manufacturers to a default manufacturer) to avoid data loss. -## Description +## Overview -The Shopware Migration Assistant establishes a connection between a data source (e.g. Shopware 5 shop) and Shopware 6 and guides you step by step through the migration process. +- [Documentation](#documentation) +- [Shopware 5](#shopware-5-migration-connector) +- [Requirements](#requirements) +- [Installation](#installation-shopware-6-project) +- [Developer setup](#developer-setup) +- [Common workflows](#common-workflows) +- [Release notes / upgrades](#release-notes--upgrades) +- [License](#license) -You can migrate numerous datasets – e.g. products, manufacturers, customers, etc. – from your existing shop system to Shopware 6 and update them at any time. +## Documentation -The assistant also makes it possible to connect two systems in order to make the transition as easy as possible. +- **User documentation**: [Shopware Migration docs](https://docs.shopware.com/en/migration-en) +- **Developer documentation**: [Migration Assistant developer docs](https://developer.shopware.com/docs/products/extensions/migration-assistant/) +## Shopware 5: Migration Connector +When migrating from Shopware 5, you can migrate locally or connect via the “Migration Connector” plugin from the Shopware Store: -Once the connection has been established, it saves automatically so that it can be accessed at any time. After the first complete migration, individual datasets can also be migrated or updated as needed. +- **Migration Connector**: [Shopware Store listing](https://store.shopware.com/de/swag226607479310f/migration-connector.html) +The connector provides API endpoints so Shopware 6 can establish a secure connection to the Shopware 5 shop. Keep it enabled as long as you need updates/delta migrations. +## Requirements -Before the migration takes place, the assistant performs a data check to determine missing or unassignable datasets. Within the scope of this check it may be necessary to create so-called “mapping”, which replaces any missing data with an assignment (e.g. missing manufacturer data automatically reverts to the default manufacturer) – this ensures you can quickly migrate without losing any data. +- **Shopware**: `shopware/core` (see version here [`composer.json`](composer.json)) +- **Node.js / npm**: required for administration and JS tooling (lint/unit/acceptance) +- **MySQL client**: required for importing Shopware 5 fixture data (optional) +## Installation (Shopware 6 project) +Expected path (relative to your Shopware 6 project root) for the plugin: -## Info for Shopware 5 users: +`custom/plugins/SwagMigrationAssistant` -In migrating your Shopware 5 shop, you can either perform the migration locally or use the “Migration Connector” plugin [Link to the plugin](https://store.shopware.com/de/swag226607479310f/migration-connector.html). +From the shopware root directory: +```bash +bin/console plugin:refresh +bin/console plugin:install -a -c SwagMigrationAssistant +``` +Alternatively, use the provided shortcut: -The Migration Connector provides API endpoints that allow Shopware 6 to establish a secure data connection with the active Shopware 5 shop. As long as you are using Shopware 6, you should leave the plugin enabled. This is the only way to update the data at any time. +```bash +composer setup +``` +## Developer setup +- **Install JS dependencies** (administration + Jest + Playwright project): -## Get started with the Migration Assistant: +```bash +composer npm:init +``` +- **Install git pre-commit hook** (optional): +```bash +./bin/setup.sh +``` -- Download the Shopware Migration Assistant from the Community Store -- Activate the plugin in your Shopware 6 installation – this can be done in the Plugin Manager under “Purchases”. Alternatively, you can use the Plugin Manager to upload the plugin ZIP file. -- The Migration Assistant will then guide you through the migration process. +## Common workflows -## Documentation +### Linting & formatting + +Run everything (PHP + admin): + +```bash +composer lint +``` + +Run individual parts: + +```bash +composer ecs +composer phpstan +composer phpunit +composer admin:lint # eslint +composer admin:format # prettier +``` + +### Tests + +- **PHPUnit**: + +```bash +composer phpunit +``` + +- **Administration unit tests (Jest)**: + +```bash +composer admin:unit +``` + +- **Acceptance tests (Playwright)**: + +```bash +composer admin:acceptance +``` + +More details (including Playwright install steps) can be found in the [acceptance tests README](tests/acceptance/README.md). + +### Import Shopware 5 fixture database (optional) + +This imports `tests/_fixtures/database/sw55.sql` into the database configured in your Shopware root `.env` via `DATABASE_URL`. + +```bash +composer install5db +``` + +## Release notes / upgrades + +- **Changelog**: [`CHANGELOG.md`](CHANGELOG.md) +- **Breaking changes**: [`UPGRADE.md`](UPGRADE.md) + +## License -If you need further information. You can have a look at our [user documentation](https://docs.shopware.com/en/migration-en) and our [developer documentation](https://developer.shopware.com/docs/products/extensions/migration-assistant/) +`MIT` See [`LICENSE`](LICENSE). diff --git a/UPGRADE.md b/UPGRADE.md index df5a396fe..d454fcac6 100644 --- a/UPGRADE.md +++ b/UPGRADE.md @@ -1,4 +1,242 @@ +# 16.0.0 + +- [BREAKING] [#114](https://github.com/shopware/SwagMigrationAssistant/pull/114) - fix: use item-specific tax in order conversion + - [BREAKING] Removed parameter `taxRules` from method `getLineItems` of `SwagMigrationAssistant\Profile\Shopware\Converter\OrderConverter` + +- [BREAKING] [#102](https://github.com/shopware/SwagMigrationAssistant/pull/102) - refactor!: use domain exception + - [BREAKING] Removed standalone exception classes in `SwagMigrationAssistant\Exception\**\*`: + - `SwagMigrationAssistant\Exception\AssociationEntityRequiredMissingException` + - `SwagMigrationAssistant\Exception\ConverterNotFoundException` + - `SwagMigrationAssistant\Exception\DataSetNotFoundException` + - `SwagMigrationAssistant\Exception\GatewayReadException` + - `SwagMigrationAssistant\Exception\LocaleNotFoundException` + - `SwagMigrationAssistant\Exception\MigrationIsAlreadyRunningException` + - `SwagMigrationAssistant\Exception\NoConnectionFoundException` + - `SwagMigrationAssistant\Exception\NoRunningMigrationException` + - `SwagMigrationAssistant\Exception\PremappingIsIncompleteException` + - `SwagMigrationAssistant\Exception\WriterNotFoundException` + +- [BREAKING] [#100](https://github.com/shopware/SwagMigrationAssistant/pull/100) - refactor!: unify public api + - [BREAKING] Flagged `SwagMigrationAssistant\Controller\DataProviderController` as `@internal` and added parent class of `Symfony\Bundle\FrameworkBundle\Controller\AbstractController` + - [BREAKING] Flagged `SwagMigrationAssistant\Controller\HistoryController` as `@internal` + - [BREAKING] Flagged `SwagMigrationAssistant\Controller\PremappingController` as `@internal` + - [BREAKING] Flagged `SwagMigrationAssistant\Controller\StatusController` as `@internal` + - [BREAKING] Flagged `SwagMigrationAssistant\Core\Migration\**\*` migrations as `@internal` + - [BREAKING] Flagged `SwagMigrationAssistant\DataProvider\Service\EnvironmentService` as `@internal` + - [BREAKING] Flagged `SwagMigrationAssistant\Migration\Connection\Helper\ConnectionNameSanitizer` as `@internal` + - [BREAKING] Removed error code `FAILED_TO_CREATE_MIGRATION_LOG` and exception method `failedToCreateMigrationLog()` of `SwagMigrationAssistant\Exception\MigrationException` + - Added event class `MigrationPreErrorResolutionEvent` to allow extensions to hook into the pre error resolution step + - Added event class `MigrationPostErrorResolutionEvent` to allow extensions to hook into the post error resolution step + - Added class `MigrationErrorResolutionContext` to pass error resolution related context data + +- [#85](https://github.com/shopware/SwagMigrationAssistant/pull/85) - refactor: use xxh hash + - Changed checksum calculation in `SwagMigrationAssistant\Migration\Converter\Converter::generateChecksum()` to use `Shopware\Core\Framework\Util\Hasher::hash()` and its default `xxh128` algorithm instead of `md5` + - Changed to use `Shopware\Core\Framework\Util\Hasher::hash()` for every use of hashing in `SwagMigrationAssistant\**\*` + +- [BREAKING] [#82](https://github.com/shopware/SwagMigrationAssistant/pull/82) - refactor!: change swag migration mapping + - [BREAKING] Renamed table column `entity_uuid` of `swag_migration_mapping` to `entity_id` with `SwagMigrationAssistant\Core\Migration\Migration1762346793RenameColumnOfMappingTable` + - [BREAKING] Changed field `entityUuid` to `entityId` in `SwagMigrationAssistant\Migration\Mapping\SwagMigrationMappingDefinition` and `SwagMigrationAssistant\Migration\Mapping\SwagMigrationMappingEntity` + - [BREAKING] Renamed every occurrence of `entityUuid` to `entityId` in `SwagMigrationAssistant\**\*`, most relevant for: + - `SwagMigrationAssistant\Migration\Mapping\MappingService` + - `SwagMigrationAssistant\Migration\Mapping\MappingServiceInterface` + - `SwagMigrationAssistant\Profile\Shopware\Converter\**\*` + - `SwagMigrationAssistant\Profile\Shopware6\Converter\**\*` + +- [BREAKING] [#79](https://github.com/shopware/SwagMigrationAssistant/pull/79) - refactor!: remove validation from converter + - [BREAKING] Changed method `convert()` of `SwagMigrationAssistant\Migration\Converter\ConverterInterface` to have nullable return type of `?ConverterStruct` + +- [BREAKING] [#77](https://github.com/shopware/SwagMigrationAssistant/pull/77) - feat!: add acl constraints + - Added acl privilege mapping to `src/Resources/app/administration/src/module/swag-migration/acl/index.ts` + - [BREAKING] Added acl constraint for route `/migration/get-grouped-logs-of-run` from `SwagMigrationAssistant\Controller\HistoryController::getGroupedLogsOfRun()` requiring privilege `swag_migration.viewer` + - [BREAKING] Added acl constraint for route `/migration/download-logs-of-run` from `SwagMigrationAssistant\Controller\HistoryController::downloadLogsOfRun()` requiring privilege `swag_migration.viewer` + - [BREAKING] Added acl constraint for route `/migration/clear-data-of-run` from `SwagMigrationAssistant\Controller\HistoryController::clearDataOfRun()` requiring privilege `swag_migration.deleter` + - [BREAKING] Added acl constraint for route `/migration/is-media-processing` from `SwagMigrationAssistant\Controller\HistoryController::isMediaProcessing()` requiring privilege `swag_migration.viewer` + - [BREAKING] Added acl constraint for route `/migration/generate-premapping` from `SwagMigrationAssistant\Controller\PremappingController::generatePremapping()` requiring privilege `swag_migration.editor` + - [BREAKING] Added acl constraint for route `/migration/write-premapping` from `SwagMigrationAssistant\Controller\PremappingController::writePremapping()` requiring privilege `swag_migration.editor` + - [BREAKING] Added acl constraint for route `/migration/get-profile-information` from `SwagMigrationAssistant\Controller\StatusController::getProfileInformation()` requiring privilege `swag_migration.viewer` + - [BREAKING] Added acl constraint for route `/migration/get-profiles` from `SwagMigrationAssistant\Controller\StatusController::getProfiles()` requiring privilege `swag_migration.viewer` + - [BREAKING] Added acl constraint for route `/migration/get-gateways` from `SwagMigrationAssistant\Controller\StatusController::getGateways()` requiring privilege `swag_migration.viewer` + - [BREAKING] Added acl constraint for route `/migration/data-selection` from `SwagMigrationAssistant\Controller\StatusController::getDataSelection()` requiring privilege `swag_migration.editor` + - [BREAKING] Added acl constraint for route `/migration/check-connection` from `SwagMigrationAssistant\Controller\StatusController::getDataSelection()` requiring privilege `swag_migration.viewer` + - [BREAKING] Added acl constraint for route `/migration/start-migration` from `SwagMigrationAssistant\Controller\StatusController::startMigration()` requiring privilege `swag_migration.creator` + - [BREAKING] Added acl constraint for route `/migration/get-state` from `SwagMigrationAssistant\Controller\StatusController::getState()` requiring privilege `swag_migration.viewer` + - [BREAKING] Added acl constraint for route `/migration/approve-finished` from `SwagMigrationAssistant\Controller\StatusController::approveFinishedMigration()` requiring privilege `swag_migration.editor` + - [BREAKING] Added acl constraint for route `/migration/abort-migration` from `SwagMigrationAssistant\Controller\StatusController::abortMigration()` requiring privilege `swag_migration.editor` + - [BREAKING] Added acl constraint for route `/migration/reset-checksums` from `SwagMigrationAssistant\Controller\StatusController::resetChecksums()` requiring privilege `swag_migration.deleter` + - [BREAKING] Added acl constraint for route `/migration/cleanup-migration-data` from `SwagMigrationAssistant\Controller\StatusController::cleanupMigrationData()` requiring privilege `swag_migration.deleter` + - [BREAKING] Added acl constraint for route `/migration/is-truncating-migration-data` from `SwagMigrationAssistant\Controller\StatusController::isTruncatingMigrationData()` requiring privilege `swag_migration.viewer` + - [BREAKING] Added acl constraint for route `/migration/is-resetting-checksums` from `SwagMigrationAssistant\Controller\StatusController::isResettingChecksums()` requiring privilege `swag_migration.viewer` + +- [#76](https://github.com/shopware/SwagMigrationAssistant/pull/76) - feat: add any json field + - Added DAL Field class `SwagMigrationAssistant\Core\Field\AnyJsonField` to handle JSON data with any structure + - Added DAL Field Serializer class `SwagMigrationAssistant\Core\Field\AnyJsonFieldSerializer` to encode and decode `AnyJsonField` data + +- [BREAKING] [#74](https://github.com/shopware/SwagMigrationAssistant/pull/74) - feat!: split message queue process + - [BREAKING] Changed method `getProcessor()` of `SwagMigrationAssistant\Migration\MessageQueue\Handler\MigrationProcessorRegistry` to return `null` if no processor is needed for the given migration step + - Added route `/migration/resume-after-fixes` to `SwagMigrationAssistant\Controller\StatusController::resumeAfterFixes()` to resume migration after user applied fixes in error resolution step + - Added migration step `error-resolution` to `SwagMigrationAssistant\Migration\Run\MigrationStep` + - Added method `needsProcessor()` to `SwagMigrationAssistant\Migration\Run\MigrationStep` to indicate if a migration step needs a message queue processor + - Added required method `resumeAfterFixes()` to `SwagMigrationAssistant\Migration\Run\RunServiceInterface` and implementation `SwagMigrationAssistant\Migration\Run\RunService` to resume migration after user applied fixes in error resolution step + - Changed order of migration steps in `src/Resources/app/administration/src/module/swag-migration/page/swag-migration-process-screen/index.ts` + +- [#64](https://github.com/shopware/SwagMigrationAssistant/pull/64) - fix: adjust log file generation + - Changed log time format from `d.m.Y h:i:s e` to `Y-m-d H:i:s T` in `SwagMigrationAssistant\Migration\History\HistoryService` + - Adjusted log file generation in `SwagMigrationAssistant\Migration\History\HistoryService` to include new required & optional fields of migration logs and removed truncated fields + +- [BREAKING] [#63](https://github.com/shopware/SwagMigrationAssistant/pull/63) - feat!: apply fixes prototype + - Added class `SwagMigrationAssistant\Migration\ErrorResolution\MigrationFix` to represent a migration fix + - Added class `SwagMigrationAssistant\Migration\ErrorResolution\MigrationErrorResolutionService` to manage migration fixes + - [BREAKING] Added argument `$errorResolutionService` to constructor of `SwagMigrationAssistant\Migration\Service\MigrationDataWriter` + - [BREAKING] Changed method `writeData(...)` of `SwagMigrationAssistant\Migration\Service\MigrationDataWriter` to apply migration fixes before data writing calling `SwagMigrationAssistant\Migration\ErrorResolution::applyFixes(...)` + +- [BREAKING] [#60](https://github.com/shopware/SwagMigrationAssistant/pull/60) - chore!: drop migration cli commands + - [BREAKING] Removed command `migration:abort` from `SwagMigrationAssistant\Command\AbortMigrationCommand` in favor of message queue based execution + - [BREAKING] Removed command `migration:get-progress` from `SwagMigrationAssistant\Command\GetMigrationProgressCommand` in favor of message queue based execution + - [BREAKING] Removed command `migration:start` from `SwagMigrationAssistant\Command\StartMigrationCommand` in favor of message queue based execution + +- [#58](https://github.com/shopware/SwagMigrationAssistant/pull/58) - refactor: use meteor tokens + - Replaced hardcoded colors, spacing, font-sizes, etc. and polished styling in administration components with [meteor tokens](https://shopware.design/tokens) for unified styling + - Removed unused component `swag-migration-expand-div` + +- [BREAKING] [#57](https://github.com/shopware/SwagMigrationAssistant/pull/57) - feat!: checksum and reset via mq + - Added new message `SwagMigrationAssistant\Migration\MessageQueue\Message\ResetChecksumMessage` to trigger checksum reset via message queue + - [BREAKING] Renamed message `SwagMigrationAssistant\Migration\MessageQueue\Message\CleanupMigrationMessage` to `TruncateMigrationMessage` for consistency + - Changed `StatusController::resetChecksums()` it now dispatches `ResetChecksumMessage` to message bus instead of executing directly + - Changed `StatusController::cleanupMigrationData()` it now dispatches `TruncateMigrationMessage` to message bus instead of executing directly + - Added `StatusController::isResettingChecksums()` and route `/migration/is-resetting-checksums` to check if checksum reset is in progress + - Added column `is_resetting_checksums` to `swag_migration_general_setting` to store checksum reset state with `SwagMigrationAssistant\Core\Migration\Migration1759000000AddIsResettingChecksumsToSetting` + - Removed `$runService` argument from constructor of `SwagMigrationAssistant\Migration\MessageQueue\Handler\Processor\AbortingProcessor` + - Changed name of `$dbalConnection` constructor argument of `SwagMigrationAssistant\Migration\MessageQueue\Handler\Processor\CleanUpProcessor` to `$connection` for consistency + - Added new message queue Handler class `SwagMigrationAssistant\Migration\MessageQueue\Handler\ResetChecksumHandler` to handle checksum reset message `ResetChecksumMessage` + - [BREAKING] Renamed `SwagMigrationAssistant\Migration\MessageQueue\Handler\CleanupMigrationHandler` to `TruncateMigrationHandler` for consistency + - Added polling logic to `src/Resources/app/administration/src/module/swag-migration/component/card/swag-migration-shop-information/swag-migration-shop-information.html.twig` to check if checksum reset or migration truncate is in progress + - [BREAKING] Removed argument `$migrationDataDefinition` from constructor of `SwagMigrationAssistant\Migration\Run\RunService` as it is no longer needed + - [BREAKING] Renamed method `cleanupMappingChecksums()` of `SwagMigrationAssistant\Migration\Run\RunService` to `startCleanupMappingChecksums()` to indicate that it starts the process via message queue + - [BREAKING] Renamed method `cleanupMigrationData()` of `SwagMigrationAssistant\Migration\Run\RunService` to `startTruncateMigrationData()` to indicate that it starts the process via message queue + - [BREAKING] Renamed method and route `StatusController::isResettingChecksums()` to `isTruncatingMigrationData()` and `/migration/is-truncating-migration-data` to check if migration data truncation is in progress + - [BREAKING] Renamed method `cleanupMappingChecksums()` to `startCleanupMappingChecksums()` in `SwagMigrationAssistant\Migration\Run\RunServiceInterface` and implementation `SwagMigrationAssistant\Migration\Run\RunService` + - [BREAKING] Renamed method `cleanupMigrationData()` to `startTruncateMigrationData()` in `SwagMigrationAssistant\Migration\Run\RunServiceInterface` and implementation `SwagMigrationAssistant\Migration\Run\RunService` + +- [#56](https://github.com/shopware/SwagMigrationAssistant/pull/56) - feat: add migration fixes table + - Added new entity `SwagMigrationFixEntity`, definition `SwagMigrationFixDefinition` and collection `SwagMigrationFixCollection` to store available migration fixes + - Added new table `swag_migration_fix` with `SwagMigrationAssistant\Core\Migration\Migration1757598733AddMigrationFixesTable` + +- [BREAKING] [#53](https://github.com/shopware/SwagMigrationAssistant/pull/53) - feat!: add error resolution ui + - [BREAKING] Added argument `$logGroupingService` to constructor of `SwagMigrationAssistant\Controller\HistoryController` + - [BREAKING] Changed method signature of `SwagMigrationAssistant\Migration\Gateway\GatewayRegistry::getGateways()` and `GatewayRegistryInterface` to require `MigrationContextInterface` as parameter + - [BREAKING] Changed `$run` property and method `getRun()` return type of `SwagMigrationAssistant\Migration\Logging\SwagMigrationLoggingEntity` to be nullable + - Added new service `SwagMigrationAssistant\Migration\History\LogGroupingService` to group migration logs by entity and source id for error resolution step + - Added route `/migration/get-log-groups` to `SwagMigrationAssistant\Controller\HistoryController::getLogGroups()` to fetch grouped migration logs for error resolution step + - Added route `/migration/get-all-log-ids` to `SwagMigrationAssistant\Controller\HistoryController::getAllLogIds()` to fetch all log ids of a migration run for error resolution step + - Added new administration service `src/module/swag-migration/service/swag-migration-error-resolution.service.ts` + - Added new administration components to `src/module/swag-migration/component/swag-migration-error-resolution/**/*`: + - `swag-migration-error-resolution-step` + - `swag-migration-error-resolution-modal` + - `swag-migration-error-resolution-details-modal` + - `swag-migration-error-resolution-log-filter` + - `swag-migration-error-resolution-field` + - `swag-migration-error-resolution-field-relation` + - `swag-migration-error-resolution-field-scalar` + - `swag-migration-error-resolution-field-unhandled` + +- [BREAKING] [#51](https://github.com/shopware/SwagMigrationAssistant/pull/51) - feat!: add migration validation of converted data + - [BREAKING] Added validation check of converted data to `convertData(...)` method in `SwagMigrationAssistant\Migration\Service\MigrationDataConverter` + - Added `hasValidMappingByEntityId(...)` to `SwagMigrationAssistant\Migration\Mapping\MappingService` and `SwagMigrationAssistant\Migration\Mapping\MappingServiceInterface` to check if a mapping exists and is valid for a given entity and source id + - Added new service `SwagMigrationAssistant\Migration\Validation\MigrationValidationService` to validate converted data against Shopware's data definitions + - Added new events `SwagMigrationAssistant\Migration\Validation\Event\MigrationPreValidationEvent` and `SwagMigrationAssistant\Migration\Validation\Event\MigrationPostValidationEvent` to allow extensions to hook into the validation process + - Added new log classes `ValidationInvalidFieldValueLog`, `ValidationInvalidForeignKeyLog`, `ValidationMissingRequiredFieldLog` and `ValidationUnexpectedFieldLog` to log validation errors + - Added new context class `SwagMigrationAssistant\Migration\Validation\MigrationValidationContext` to pass validation related data + - Added new result class `SwagMigrationAssistant\Migration\Validation\MigrationValidationResult` to collect validation results + - Added new service `SwagMigrationAssistant\Migration\Validation\MigrationValidationService` to validate converted data against Shopware's data definitions in three steps: + - Entity structure: Check for unexpected fields + - Field Validation: Check for missing required fields and invalid field values + - Association Validation: Check for invalid foreign keys + +- [#49](https://github.com/shopware/SwagMigrationAssistant/pull/49) - feat: fill logs with meaningful data + - Added more meaningful data to log entries created in `SwagMigrationAssistant\Profile\Shopware\Logging\*` classes + - Added `MigrationLogBuilder` usage across SwagMigrationAssistant to create logs in a consistent way + +- [#42](https://github.com/shopware/SwagMigrationAssistant/pull/42) - feat: refactor connection credentials page + - Removed component `swag-migration-wizard-page-profile-information` as its step `profileInformation` in the connection wizard was removed + +- [BREAKING] [#43](https://github.com/shopware/SwagMigrationAssistant/pull/43) refactor!: migration connection usage + - [BREAKING] Changed signature of method `supports()` in `SwagMigrationAssistant\Migration\Gateway\GatewayInterface` to require `ProfileInterface` as parameter instead of `MigrationContextInterface` + - [BREAKING] Changed signature of method `getGateways()` in `SwagMigrationAssistant\Migration\Gateway\GatewayRegistryInterface` to require `ProfileInterface` as parameter instead of `MigrationContextInterface` + - [BREAKING] Changed signature of method `getGateways()` in `SwagMigrationAssistant\Migration\Gateway\GatewayRegistry` to require `ProfileInterface` as parameter instead of `MigrationContextInterface` + - [BREAKING] Changed signature of constructor method of `SwagMigrationAssistant\Migration\MigrationContext` to require `SwagMigrationConnectionEntity` and additional optional parameter of `ProfileInterface` with default value `null` + - Added methods `setProfile()`, `getGateway()`, `setGateway()` and `setConnection()` to `SwagMigrationAssistant\Migration\MigrationContextInterface` + - Added methods `setProfile()`, `getGateway()`, `setGateway()` and `setConnection()` to `SwagMigrationAssistant\Migration\MigrationContext` + - Added null checks to methods `getProfile()` and `getGateway()` in `SwagMigrationAssistant\Migration\MigrationContext` to ensure that a profile and gateway is set before usage + +- [BREAKING] [#40](https://github.com/shopware/SwagMigrationAssistant/pull/40) - refactor!: add migration logging optional fields + - [BREAKING] Replaced `SwagMigrationAssistant\Migration\Logging\Log\BaseRunLogEntity` with `SwagMigrationAssistant\Migration\Logging\Log\Builder\AbstractMigrationLogEntry` + - [BREAKING] Replaced `SwagMigrationAssistant\Migration\Logging\Log\LogEntryInterface` with `SwagMigrationAssistant\Migration\Logging\Log\Builder\MigrationLogEntry` + - [BREAKING] Updated all log implementations in `SwagMigrationAssistant\Migration\Logging\Log\*` and `SwagMigrationAssistant\Profile\**\Logging\*`: + - extend `SwagMigrationAssistant\Migration\Logging\Log\Builder\AbstractMigrationLogEntry` instead of `SwagMigrationAssistant\Migration\Logging\Log\BaseRunLogEntity` + - implement `SwagMigrationAssistant\Migration\Logging\Log\Builder\MigrationLogEntry` instead of `SwagMigrationAssistant\Migration\Logging\Log\LogEntryInterface` + - mark class readonly + - [BREAKING] Renamed log classes to include `Log` suffix + - `SwagMigrationAssistant\Migration\Logging\LogCannotConvertChildEntity`, + - `SwagMigrationAssistant\Migration\Logging\LogCannotConvertEntity`, + - `SwagMigrationAssistant\Migration\Logging\LogDocumentTypeNotSupported`, + - `SwagMigrationAssistant\Migration\Logging\LogInvalidUnserializedData`, + - `SwagMigrationAssistant\Migration\Logging\LogRunAbortedAutomatically` + - `SwagMigrationAssistant\Migration\Logging\LogUnsupportedObjectType` + - [BREAKING] Change method `addLogEntry()` of `SwagMigrationAssistant\Migration\Logging\LoggingServiceInterface` and implementation `LoggingService` to require `MigrationLogEntry` as parameter instead of `LogEntryInterface` + - Created `SwagMigrationAssistant\Migration\Logging\Log\Builder\MigrationLogBuilder` to build log entries of type `MigrationLogEntry` + - Added columns to `swag_migration_logging` with `SwagMigrationAssistant\Core\Migration\Migration1754897550AddRequiredFieldsToMigrationLogs`: + - `entity_name` + - `entity_id` + - `field_name` + - `field_source_path` + - `source_data` + - `converted_data` + - `exception_message` + - `exception_trace` + - Added fields to `swag_migration_logging` to log definition `SwagMigrationAssistant\Migration\Logging\SwagMigrationLoggingDefinition`: + - `entity_name` + - `field_name` + - `field_source_path` + - `source_data` + - `converted_data` + - `used_mapping` + - `exception_message` + - `exception_trace` + - Added properties and methods to log entity `SwagMigrationAssistant\Migration\Logging\SwagMigrationLoggingEntity`: + - `entityName` and `getEntityName()` + - `fieldName` and `getFieldName()` + - `fieldSourcePath` and `getFieldSourcePath()` + - `sourceData` and `getSourceData()` + - `convertedData` and `getConvertedData()` + - `usedMapping` and `getUsedMapping()` + - `exceptionMessage` and `getExceptionMessage()` + - `exceptionTrace` and `getExceptionTrace()` + +- [BREAKING] [#39](https://github.com/shopware/SwagMigrationAssistant/pull/39) - refactor!: convert to ts + - [BREAKING] Changed all javascript files in `src/Resources/app/administration/**/*` to typescript files + - [BREAKING] Moved `src/core/data/migration.store.js` into owning module `src/module/swag-migration/store/migration.store.ts` + - Introduced `Shopware.Component.wrapComponentConfig(...)` to wrap component configurations for all components + - Introduced usage of [meteor tokens](https://shopware.design/tokens) for unified styling + - Removed dynamic profile component loading from `src/module/swag-migration/profile/index.js` in favor of static imports + - Added `src/type/types.d.ts` to define shared types across the administration modules + - Removed old configurations from `src/app/administration/**` + - Added `prettier` configuration to `.prettierrc.json` for consistent code formatting + +- [BREAKING] [#38](https://github.com/shopware/SwagMigrationAssistant/pull/38) - feat!: add migration logging required fields + - [BREAKING] Truncated database entries of `swag_migration_logging` with `SwagMigrationAssistant\Core\Migration\Migration1754896654TruncateMigrationLogs` + - [BREAKING] Deleted columns `title`, `description`, `parameters`, `title_snippet`, `description_snippet`, `entity` and `source_id` from `swag_migration_logging` with `SwagMigrationAssistant\Core\Migration\Migration1754897550AddRequiredFieldsToMigrationLogs` + - [BREAKING] Removed fields `title`, `description`, `parameters`, `title_snippet`, `description_snippet`, `entity` and `source_id` from log definition `SwagMigrationAssistant\Migration\Logging\SwagMigrationLoggingDefinition` + - [BREAKING] Removed properties `title`, `description`, `parameters`, `titleSnippet`, `descriptionSnippet`, `entity` and `sourceId` from log entity `SwagMigrationAssistant\Migration\Logging\SwagMigrationLoggingEntity` + - [BREAKING] Removed aggregations of `titleSnippet`, `entity` and `level` in `SwagMigrationAssistant\Migration\History\HistoryService` + - [BREAKING] Updated all log implementations in `SwagMigrationAssistant\Migration\Logging\Log\*` and `SwagMigrationAssistant\Profile\**\Logging\*`: + - deleted methods `getTitle()`, `getTitleSnippet()`, `getDescription()`, `getDescriptionSnippet()`, `getParameters()`, `getSourceId()` + - add method `isUserFixable()` + - Added columns `profile_name`, `gateway_name` and `user_fixable` to `swag_migration_logging` with `SwagMigrationAssistant\Core\Migration\Migration1754897550AddRequiredFieldsToMigrationLogs` + - Added fields `profile_name`, `gateway_name` and `user_fixable` to log definition `SwagMigrationAssistant\Migration\Logging\SwagMigrationLoggingDefinition` + - Added properties `profileName`, `gatewayName` and `userFixable` to log entity `SwagMigrationAssistant\Migration\Logging\SwagMigrationLoggingEntity` + # 14.0.0 + - [BREAKING] MIG-1053 - Removed ability to set the `verify` flag for the guzzle API client. This is now always true by default. - [BREAKING] MIG-1053 - Refactored both Shopware 5 and Shopware 6 EnvironmentReader classes to provide more information about exceptions. - MIG-894 - Optimizes the mapping performance for the migration which results in a significantly faster converting step. @@ -16,7 +254,7 @@ - Added new class `SwagMigrationAssistant\Migration\Mapping\Lookup\NumberRangeLookup` to replace the removed method `getNumberRangeUuid` - Added new class `SwagMigrationAssistant\Migration\Mapping\Lookup\TaxLookup` to replace the removed method `getTaxUuid` - Added new class `SwagMigrationAssistant\Migration\Mapping\Lookup\SeoUrlTemplateLookup` to replace the removed method `getSeoUrlTemplateUuid` - - [BREAKING] Added new constructor parameter `LowestRootCategoryLookup $lowestRootCategoryLookup`. `DefaultCmsPageLookup $defaultCmsPageLookup`, `LanguageLookup $languageLookup` to `SwagMigrationAssistant\Profile\Shopware\Converter\CategoryConverter` + - [BREAKING] Added new constructor parameter `LowestRootCategoryLookup $lowestRootCategoryLookup`, `DefaultCmsPageLookup $defaultCmsPageLookup`, `LanguageLookup $languageLookup` to `SwagMigrationAssistant\Profile\Shopware\Converter\CategoryConverter` - [BREAKING] Added new constructor parameter `CurrencyLookup $currencyLookup`, `LanguageLookup $languageLookup` to `SwagMigrationAssistant\Profile\Shopware\Converter\CurrencyConverter` - [BREAKING] Added new constructor parameter `CountryLookup $countryLookup`, `LanguageLookup $languageLookup`, `CountryStateLookup $countryStateLookup` to `SwagMigrationAssistant\Profile\Shopware\Converter\CustomerConverter` - [BREAKING] Added new constructor parameter `LanguageLookup $languageLookup` to `SwagMigrationAssistant\Profile\Shopware\Converter\CustomerGroupConverter` @@ -60,7 +298,7 @@ - [BREAKING] Removed method `getDocumentTypeUuid` from `SwagMigrationAssistant\Migration\Mapping\MappingServiceInterface` and all implementors. Use `SwagMigrationAssistant\Migration\Mapping\Lookup\DocumentTypeLookup::get()` instead. - [BREAKING] Removed method `getLowestRootCategoryUuid` from `SwagMigrationAssistant\Migration\Mapping\MappingServiceInterface` and all implementors. Use `SwagMigrationAssistant\Migration\Mapping\Lookup\LowestRootCategoryLookup::get()` instead. - [BREAKING] Change signature of function `writeMapping` from `public function writeMapping(Context $context): void;` to `public function writeMapping(): void;` in `SwagMigrationAssistant\Migration\Mapping\MappingServiceInterface` and all implementors. - - [BREAKING] Removed constructor parameter `EntityRepository $localeRepository`, `EntityRepository $languageRepository`, `EntityRepository $countryRepository`, `EntityRepository $currencyRepository`, `EntityRepository $taxRepo`, `EntityRepository $numberRangeRepo`, `EntityRepository $ruleRepo`, `EntityRepository $thumbnailSizeRepo`, `EntityRepository $mediaDefaultRepo`, `EntityRepository $categoryRepo`, `EntityRepository $cmsPageRepo`, `EntityRepository $deliveryTimeRepo`, `EntityRepository $documentTypeRepo` from `\SwagMigrationAssistant\Profile\Shopware6\Mapping\Shopware6MappingService` + - [BREAKING] Removed constructor parameter `EntityRepository $localeRepository`, `EntityRepository $languageRepository`, `EntityRepository $countryRepository`, `EntityRepository $currencyRepository`, `EntityRepository $taxRepo`, `EntityRepository $numberRangeRepo`, `EntityRepository $ruleRepo`, `EntityRepository $thumbnailSizeRepo`, `EntityRepository $mediaDefaultRepo`, `EntityRepository $categoryRepo`, `EntityRepository $cmsPageRepo`, `EntityRepository $deliveryTimeRepo`, `EntityRepository $documentTypeRepo` from `\SwagMigrationAssistant\Profile\Shopware6\Mapping\Shopware6MappingService` - MIG-1039 - [BREAKING] Added new method `getCountryStateUuid` to `SwagMigrationAssistant\Migration\Mapping\MappingServiceInterface` - MIG-1039 - [BREAKING] Added new constructor parameter `EntityRepository $countryStateRepo` to `SwagMigrationAssistant\Migration\Mapping\MappingService` - MIG-1049 - Made `connection` property of `SwagMigrationMappingEntity` optional diff --git a/bin/install-5-test-data.sh b/bin/install-5-test-data.sh index 8ed0eb154..f49723724 100755 --- a/bin/install-5-test-data.sh +++ b/bin/install-5-test-data.sh @@ -26,4 +26,4 @@ echo "MySQL host: $host" echo "MySQL user: $user" # import test data -mysql -u"$user" -p"$password" --host "$host" < tests/testData/sw55.sql +mysql -u"$user" -p"$password" --host "$host" < tests/_fixtures/database/sw55.sql diff --git a/composer.json b/composer.json index 575018f94..deb970c59 100644 --- a/composer.json +++ b/composer.json @@ -38,7 +38,8 @@ "@ecs-fix", "@phpstan", "@phpunit", - "@admin:lint" + "@lint:admin", + "@format:admin" ], "ecs": "../../../vendor/bin/php-cs-fixer fix --dry-run", "ecs-fix": "../../../vendor/bin/php-cs-fixer fix", @@ -59,27 +60,44 @@ "@npm:jest install", "@npm:acceptance install" ], - "admin:lint": [ + "lint:admin": [ "@npm:jest run lint", "@npm:admin run lint", "@npm:acceptance run lint", "@npm:admin run lint:scss" ], - "admin:lint:fix": [ - "@npm:jest run lint-fix", - "@npm:admin run lint-fix", - "@npm:acceptance run lint-fix", - "@npm:admin run lint:scss-fix" + "lint:admin:fix": [ + "@npm:jest run lint:fix", + "@npm:admin run lint:fix", + "@npm:acceptance run lint:fix", + "@npm:admin run lint:scss:fix" ], - "admin:lint:scss": [ + "lint:admin:scss": [ "@npm:admin run lint:scss" ], + "format:admin": [ + "@npm:jest run format", + "@npm:admin run format", + "@npm:acceptance run format" + ], + "format:admin:fix": [ + "@npm:jest run format:fix", + "@npm:admin run format:fix", + "@npm:acceptance run format:fix" + ], + "format:md": "@npm:admin run format:md", + "format:md:fix": "@npm:admin run format:md:fix", "admin:unit": "@npm:jest run unit", "admin:unit:watch": "@npm:jest run unit-watch", "admin:acceptance": "@npm:acceptance run test", "npm:admin": "cd src/Resources/app/administration && npm", "npm:jest": "cd tests/Jest && npm", - "npm:acceptance": "cd tests/acceptance && npm" + "npm:acceptance": "cd tests/acceptance && npm", + "npm:init": [ + "@npm:admin install", + "@npm:jest install", + "@npm:acceptance install" + ] }, "autoload": { "psr-4": { diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index 1d01cf86e..b3503d722 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -1,1026 +1,1195 @@ parameters: ignoreErrors: - - message: '#^Property SwagMigrationAssistant\\Migration\\Converter\\Converter\:\:\$mainMapping \(array\{id\: string, connectionId\: string, oldIdentifier\: string\|null, entityUuid\: string\|null, entityValue\: string\|null, checksum\: string\|null, additionalData\: array\\|null\}\|null\) does not accept array\{additionalData\: non\-empty\-array\\}\|array\{id\: string, connectionId\: string, oldIdentifier\: string\|null, entityUuid\: string\|null, entityValue\: string\|null, checksum\: string\|null, additionalData\: non\-empty\-array\\}\.$#' - count: 1 - path: src/Migration/Converter/Converter.php - - - - message: '#^Property SwagMigrationAssistant\\Migration\\Converter\\Converter\:\:\$mainMapping \(array\{id\: string, connectionId\: string, oldIdentifier\: string\|null, entityUuid\: string\|null, entityValue\: string\|null, checksum\: string\|null, additionalData\: array\\|null\}\|null\) does not accept array\{checksum\: string\}\|array\{id\: string, connectionId\: string, oldIdentifier\: string\|null, entityUuid\: string\|null, entityValue\: string\|null, checksum\: string, additionalData\: array\\|null\}\.$#' - count: 1 - path: src/Migration/Converter/Converter.php - - - - message: "#^swag_migration_data\\.run association has a configured autoload\\=\\=\\=true, this is forbidden for platform integrations$#" + message: '#^swag_migration_data\.run association has a configured autoload\=\=\=true, this is forbidden for platform integrations$#' + identifier: shopware.associationAutoload count: 1 path: src/Migration/Data/SwagMigrationDataDefinition.php - - message: "#^Method SwagMigrationAssistant\\\\Migration\\\\History\\\\HistoryService\\:\\:extractBucketInformation\\(\\) return type has no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Migration\\History\\HistoryService\:\:extractBucketInformation\(\) return type has no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Migration/History/HistoryService.php - - message: "#^Method SwagMigrationAssistant\\\\Migration\\\\History\\\\HistoryService\\:\\:getGroupedLogsOfRun\\(\\) return type has no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Migration\\History\\HistoryService\:\:getGroupedLogsOfRun\(\) return type has no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Migration/History/HistoryService.php - - message: "#^Provide more specific return type \"SwagMigrationAssistant\\\\Migration\\\\Logging\\\\SwagMigrationLoggingCollection\" over abstract one$#" + message: '#^Provide more specific return type "SwagMigrationAssistant\\Migration\\Logging\\SwagMigrationLoggingCollection" over abstract one$#' + identifier: typePerfect.narrowReturnObjectType count: 1 path: src/Migration/History/HistoryService.php - - message: "#^Method SwagMigrationAssistant\\\\Migration\\\\History\\\\HistoryServiceInterface\\:\\:getGroupedLogsOfRun\\(\\) return type has no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Migration\\History\\HistoryServiceInterface\:\:getGroupedLogsOfRun\(\) return type has no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Migration/History/HistoryServiceInterface.php - - message: "#^Property SwagMigrationAssistant\\\\Migration\\\\Logging\\\\LoggingService\\:\\:\\$logging type has no value type specified in iterable type array\\.$#" + message: '#^Property SwagMigrationAssistant\\Migration\\Logging\\LoggingService\:\:\$logging type has no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Migration/Logging/LoggingService.php - - message: "#^Method SwagMigrationAssistant\\\\Migration\\\\Logging\\\\SwagMigrationLoggingEntity\\:\\:getParameters\\(\\) return type has no value type specified in iterable type array\\.$#" - count: 1 - path: src/Migration/Logging/SwagMigrationLoggingEntity.php - - - - message: "#^Method SwagMigrationAssistant\\\\Migration\\\\Logging\\\\SwagMigrationLoggingEntity\\:\\:setParameters\\(\\) has parameter \\$parameters with no value type specified in iterable type array\\.$#" - count: 1 - path: src/Migration/Logging/SwagMigrationLoggingEntity.php - - - - message: "#^Property SwagMigrationAssistant\\\\Migration\\\\Logging\\\\SwagMigrationLoggingEntity\\:\\:\\$parameters type has no value type specified in iterable type array\\.$#" - count: 1 - path: src/Migration/Logging/SwagMigrationLoggingEntity.php - - - - message: "#^Method SwagMigrationAssistant\\\\Migration\\\\Mapping\\\\MappingDeltaResult\\:\\:__construct\\(\\) has parameter \\$migrationData with no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Migration\\Mapping\\MappingDeltaResult\:\:__construct\(\) has parameter \$migrationData with no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Migration/Mapping/MappingDeltaResult.php - - message: "#^Method SwagMigrationAssistant\\\\Migration\\\\Mapping\\\\MappingDeltaResult\\:\\:__construct\\(\\) has parameter \\$preloadIds with no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Migration\\Mapping\\MappingDeltaResult\:\:__construct\(\) has parameter \$preloadIds with no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Migration/Mapping/MappingDeltaResult.php - - message: "#^Method SwagMigrationAssistant\\\\Migration\\\\Mapping\\\\MappingDeltaResult\\:\\:getMigrationData\\(\\) return type has no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Migration\\Mapping\\MappingDeltaResult\:\:getMigrationData\(\) return type has no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Migration/Mapping/MappingDeltaResult.php - - message: "#^Method SwagMigrationAssistant\\\\Migration\\\\Mapping\\\\MappingDeltaResult\\:\\:getPreloadIds\\(\\) return type has no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Migration\\Mapping\\MappingDeltaResult\:\:getPreloadIds\(\) return type has no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Migration/Mapping/MappingDeltaResult.php - - message: "#^Method SwagMigrationAssistant\\\\Migration\\\\Mapping\\\\MappingService\\:\\:getMappings\\(\\) has parameter \\$ids with no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Migration\\Mapping\\MappingService\:\:getMappings\(\) has parameter \$ids with no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Migration/Mapping/MappingService.php - - message: "#^Method SwagMigrationAssistant\\\\Migration\\\\Mapping\\\\MappingService\\:\\:getUuidsByEntity\\(\\) return type has no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Migration\\Mapping\\MappingService\:\:getUuidsByEntity\(\) return type has no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Migration/Mapping/MappingService.php - - message: "#^Method SwagMigrationAssistant\\\\Migration\\\\Mapping\\\\MappingService\\:\\:preloadMappings\\(\\) has parameter \\$mappingIds with no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Migration\\Mapping\\MappingService\:\:preloadMappings\(\) has parameter \$mappingIds with no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Migration/Mapping/MappingService.php - - message: "#^Method SwagMigrationAssistant\\\\Migration\\\\Mapping\\\\MappingService\\:\\:saveListMapping\\(\\) has parameter \\$mapping with no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Migration\\Mapping\\MappingService\:\:saveListMapping\(\) has parameter \$mapping with no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Migration/Mapping/MappingService.php - - message: "#^Method SwagMigrationAssistant\\\\Migration\\\\Mapping\\\\MappingService\\:\\:saveMapping\\(\\) has parameter \\$mapping with no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Migration\\Mapping\\MappingService\:\:saveMapping\(\) has parameter \$mapping with no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Migration/Mapping/MappingService.php - - message: "#^Method SwagMigrationAssistant\\\\Migration\\\\Mapping\\\\MappingService\\:\\:updateMapping\\(\\) has parameter \\$updateData with no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Migration\\Mapping\\MappingService\:\:updateMapping\(\) has parameter \$updateData with no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Migration/Mapping/MappingService.php - - message: "#^Method SwagMigrationAssistant\\\\Migration\\\\Mapping\\\\MappingService\\:\\:updateMapping\\(\\) return type has no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Migration\\Mapping\\MappingService\:\:updateMapping\(\) return type has no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Migration/Mapping/MappingService.php - - message: "#^Property SwagMigrationAssistant\\\\Migration\\\\Mapping\\\\MappingService\\:\\:\\$languageData type has no value type specified in iterable type array\\.$#" + message: '#^Property SwagMigrationAssistant\\Migration\\Mapping\\MappingService\:\:\$languageData type has no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Migration/Mapping/MappingService.php - - message: "#^Property SwagMigrationAssistant\\\\Migration\\\\Mapping\\\\MappingService\\:\\:\\$locales type has no value type specified in iterable type array\\.$#" + message: '#^Property SwagMigrationAssistant\\Migration\\Mapping\\MappingService\:\:\$locales type has no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Migration/Mapping/MappingService.php - - message: "#^Property SwagMigrationAssistant\\\\Migration\\\\Mapping\\\\MappingService\\:\\:\\$mappings type has no value type specified in iterable type array\\.$#" + message: '#^Property SwagMigrationAssistant\\Migration\\Mapping\\MappingService\:\:\$mappings type has no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Migration/Mapping/MappingService.php - - message: "#^Property SwagMigrationAssistant\\\\Migration\\\\Mapping\\\\MappingService\\:\\:\\$migratedSalesChannels type has no value type specified in iterable type array\\.$#" + message: '#^Property SwagMigrationAssistant\\Migration\\Mapping\\MappingService\:\:\$migratedSalesChannels type has no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Migration/Mapping/MappingService.php - - message: "#^Property SwagMigrationAssistant\\\\Migration\\\\Mapping\\\\MappingService\\:\\:\\$writeArray type has no value type specified in iterable type array\\.$#" + message: '#^Property SwagMigrationAssistant\\Migration\\Mapping\\MappingService\:\:\$writeArray type has no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Migration/Mapping/MappingService.php - - message: "#^Method SwagMigrationAssistant\\\\Migration\\\\Mapping\\\\MappingServiceInterface\\:\\:getMappings\\(\\) has parameter \\$ids with no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Migration\\Mapping\\MappingServiceInterface\:\:getMappings\(\) has parameter \$ids with no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Migration/Mapping/MappingServiceInterface.php - - message: "#^Method SwagMigrationAssistant\\\\Migration\\\\Mapping\\\\MappingServiceInterface\\:\\:getUuidsByEntity\\(\\) return type has no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Migration\\Mapping\\MappingServiceInterface\:\:getUuidsByEntity\(\) return type has no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Migration/Mapping/MappingServiceInterface.php - - message: "#^Method SwagMigrationAssistant\\\\Migration\\\\Mapping\\\\MappingServiceInterface\\:\\:preloadMappings\\(\\) has parameter \\$mappingIds with no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Migration\\Mapping\\MappingServiceInterface\:\:preloadMappings\(\) has parameter \$mappingIds with no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Migration/Mapping/MappingServiceInterface.php - - message: "#^Method SwagMigrationAssistant\\\\Migration\\\\Mapping\\\\MappingServiceInterface\\:\\:updateMapping\\(\\) has parameter \\$updateData with no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Migration\\Mapping\\MappingServiceInterface\:\:updateMapping\(\) has parameter \$updateData with no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Migration/Mapping/MappingServiceInterface.php - - message: "#^Method SwagMigrationAssistant\\\\Migration\\\\Mapping\\\\MappingServiceInterface\\:\\:updateMapping\\(\\) return type has no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Migration\\Mapping\\MappingServiceInterface\:\:updateMapping\(\) return type has no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Migration/Mapping/MappingServiceInterface.php - - message: "#^Class SwagMigrationAssistant\\\\Migration\\\\Mapping\\\\SwagMigrationMappingCollection extends generic class Shopware\\\\Core\\\\Framework\\\\DataAbstractionLayer\\\\EntityCollection but does not specify its types\\: TElement$#" + message: '#^Class SwagMigrationAssistant\\Migration\\Mapping\\SwagMigrationMappingCollection extends generic class Shopware\\Core\\Framework\\DataAbstractionLayer\\EntityCollection but does not specify its types\: TElement$#' + identifier: missingType.generics count: 1 path: src/Migration/Mapping/SwagMigrationMappingCollection.php - - message: "#^Change \"defineFields\\(\\)\" method visibility to \"protected\" to respect parent method visibility\\.$#" + message: '#^Change "defineFields\(\)" method visibility to "protected" to respect parent method visibility\.$#' + identifier: symplify.parentMethodVisibilityOverride count: 1 path: src/Migration/Mapping/SwagMigrationMappingDefinition.php - - message: "#^Method SwagMigrationAssistant\\\\Migration\\\\Media\\\\MediaFileService\\:\\:saveMediaFile\\(\\) has parameter \\$mediaFile with no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Migration\\Media\\MediaFileService\:\:saveMediaFile\(\) has parameter \$mediaFile with no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Migration/Media/MediaFileService.php - - message: "#^Method SwagMigrationAssistant\\\\Migration\\\\Media\\\\MediaFileService\\:\\:saveWrittenFlag\\(\\) has parameter \\$mediaUuids with no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Migration\\Media\\MediaFileService\:\:saveWrittenFlag\(\) has parameter \$mediaUuids with no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Migration/Media/MediaFileService.php - - message: "#^Method SwagMigrationAssistant\\\\Migration\\\\Media\\\\MediaFileService\\:\\:setWrittenFlag\\(\\) has parameter \\$converted with no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Migration\\Media\\MediaFileService\:\:setWrittenFlag\(\) has parameter \$converted with no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Migration/Media/MediaFileService.php - - message: "#^Property SwagMigrationAssistant\\\\Migration\\\\Media\\\\MediaFileService\\:\\:\\$uuids type has no value type specified in iterable type array\\.$#" + message: '#^Property SwagMigrationAssistant\\Migration\\Media\\MediaFileService\:\:\$uuids type has no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Migration/Media/MediaFileService.php - - message: "#^Property SwagMigrationAssistant\\\\Migration\\\\Media\\\\MediaFileService\\:\\:\\$writeArray type has no value type specified in iterable type array\\.$#" + message: '#^Property SwagMigrationAssistant\\Migration\\Media\\MediaFileService\:\:\$writeArray type has no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Migration/Media/MediaFileService.php - - message: "#^Method SwagMigrationAssistant\\\\Migration\\\\Media\\\\MediaFileServiceInterface\\:\\:saveMediaFile\\(\\) has parameter \\$mediaFile with no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Migration\\Media\\MediaFileServiceInterface\:\:saveMediaFile\(\) has parameter \$mediaFile with no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Migration/Media/MediaFileServiceInterface.php - - message: "#^Method SwagMigrationAssistant\\\\Migration\\\\Media\\\\MediaFileServiceInterface\\:\\:setWrittenFlag\\(\\) has parameter \\$converted with no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Migration\\Media\\MediaFileServiceInterface\:\:setWrittenFlag\(\) has parameter \$converted with no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Migration/Media/MediaFileServiceInterface.php - - message: "#^Method SwagMigrationAssistant\\\\Migration\\\\Media\\\\MediaProcessWorkloadStruct\\:\\:__construct\\(\\) has parameter \\$additionalData with no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Migration\\Media\\MediaProcessWorkloadStruct\:\:__construct\(\) has parameter \$additionalData with no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Migration/Media/MediaProcessWorkloadStruct.php - - message: "#^Method SwagMigrationAssistant\\\\Migration\\\\Media\\\\MediaProcessWorkloadStruct\\:\\:getAdditionalData\\(\\) return type has no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Migration\\Media\\MediaProcessWorkloadStruct\:\:getAdditionalData\(\) return type has no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Migration/Media/MediaProcessWorkloadStruct.php - - message: "#^Method SwagMigrationAssistant\\\\Migration\\\\Media\\\\MediaProcessWorkloadStruct\\:\\:setAdditionalData\\(\\) has parameter \\$additionalData with no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Migration\\Media\\MediaProcessWorkloadStruct\:\:setAdditionalData\(\) has parameter \$additionalData with no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Migration/Media/MediaProcessWorkloadStruct.php - - message: "#^Property SwagMigrationAssistant\\\\Migration\\\\Media\\\\MediaProcessWorkloadStruct\\:\\:\\$additionalData type has no value type specified in iterable type array\\.$#" + message: '#^Property SwagMigrationAssistant\\Migration\\Media\\MediaProcessWorkloadStruct\:\:\$additionalData type has no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Migration/Media/MediaProcessWorkloadStruct.php - - message: "#^Class SwagMigrationAssistant\\\\Migration\\\\Media\\\\SwagMigrationMediaFileCollection extends generic class Shopware\\\\Core\\\\Framework\\\\DataAbstractionLayer\\\\EntityCollection but does not specify its types\\: TElement$#" + message: '#^Class SwagMigrationAssistant\\Migration\\Media\\SwagMigrationMediaFileCollection extends generic class Shopware\\Core\\Framework\\DataAbstractionLayer\\EntityCollection but does not specify its types\: TElement$#' + identifier: missingType.generics count: 1 path: src/Migration/Media/SwagMigrationMediaFileCollection.php - - message: "#^Change \"defineFields\\(\\)\" method visibility to \"protected\" to respect parent method visibility\\.$#" + message: '#^Change "defineFields\(\)" method visibility to "protected" to respect parent method visibility\.$#' + identifier: symplify.parentMethodVisibilityOverride count: 1 path: src/Migration/Media/SwagMigrationMediaFileDefinition.php - - message: "#^Method SwagMigrationAssistant\\\\Migration\\\\MessageQueue\\\\OrderCountIndexer\\:\\:updateCustomer\\(\\) has parameter \\$ids with no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Migration\\MessageQueue\\OrderCountIndexer\:\:updateCustomer\(\) has parameter \$ids with no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Migration/MessageQueue/OrderCountIndexer.php - - message: "#^Method SwagMigrationAssistant\\\\Migration\\\\Run\\\\RunProgress\\:\\:setEntities\\(\\) has parameter \\$entities with no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Migration\\Run\\RunProgress\:\:setEntities\(\) has parameter \$entities with no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Migration/Run/RunProgress.php - - message: "#^swag_migration_run\\.connection association has a configured autoload\\=\\=\\=true, this is forbidden for platform integrations$#" + message: '#^swag_migration_run\.connection association has a configured autoload\=\=\=true, this is forbidden for platform integrations$#' + identifier: shopware.associationAutoload count: 1 path: src/Migration/Run/SwagMigrationRunDefinition.php - - message: "#^Method SwagMigrationAssistant\\\\Migration\\\\Run\\\\SwagMigrationRunEntity\\:\\:getEnvironmentInformation\\(\\) return type has no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Migration\\Run\\SwagMigrationRunEntity\:\:getEnvironmentInformation\(\) return type has no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Migration/Run/SwagMigrationRunEntity.php - - message: "#^Method SwagMigrationAssistant\\\\Migration\\\\Run\\\\SwagMigrationRunEntity\\:\\:getTotals\\(\\) return type has no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Migration\\Run\\SwagMigrationRunEntity\:\:getTotals\(\) return type has no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Migration/Run/SwagMigrationRunEntity.php - - message: "#^Method SwagMigrationAssistant\\\\Migration\\\\Run\\\\SwagMigrationRunEntity\\:\\:setEnvironmentInformation\\(\\) has parameter \\$environmentInformation with no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Migration\\Run\\SwagMigrationRunEntity\:\:setEnvironmentInformation\(\) has parameter \$environmentInformation with no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Migration/Run/SwagMigrationRunEntity.php - - message: "#^Method SwagMigrationAssistant\\\\Migration\\\\Run\\\\SwagMigrationRunEntity\\:\\:setTotals\\(\\) has parameter \\$totals with no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Migration\\Run\\SwagMigrationRunEntity\:\:setTotals\(\) has parameter \$totals with no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Migration/Run/SwagMigrationRunEntity.php - - message: "#^Property SwagMigrationAssistant\\\\Migration\\\\Run\\\\SwagMigrationRunEntity\\:\\:\\$environmentInformation type has no value type specified in iterable type array\\.$#" + message: '#^Property SwagMigrationAssistant\\Migration\\Run\\SwagMigrationRunEntity\:\:\$environmentInformation type has no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Migration/Run/SwagMigrationRunEntity.php - - message: "#^Property SwagMigrationAssistant\\\\Migration\\\\Run\\\\SwagMigrationRunEntity\\:\\:\\$totals type has no value type specified in iterable type array\\.$#" + message: '#^Property SwagMigrationAssistant\\Migration\\Run\\SwagMigrationRunEntity\:\:\$totals type has no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Migration/Run/SwagMigrationRunEntity.php - - message: "#^Method SwagMigrationAssistant\\\\Migration\\\\Service\\\\MigrationDataConverter\\:\\:convert\\(\\) has parameter \\$data with no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Migration\\Service\\MigrationDataConverter\:\:convert\(\) has parameter \$data with no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Migration/Service/MigrationDataConverter.php - - message: "#^Method SwagMigrationAssistant\\\\Migration\\\\Service\\\\MigrationDataConverter\\:\\:convertData\\(\\) has parameter \\$data with no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Migration\\Service\\MigrationDataConverter\:\:convertData\(\) has parameter \$data with no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Migration/Service/MigrationDataConverter.php - - message: "#^Method SwagMigrationAssistant\\\\Migration\\\\Service\\\\MigrationDataConverter\\:\\:convertData\\(\\) return type has no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Migration\\Service\\MigrationDataConverter\:\:convertData\(\) return type has no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Migration/Service/MigrationDataConverter.php - - message: "#^Method SwagMigrationAssistant\\\\Migration\\\\Service\\\\MigrationDataConverter\\:\\:filterDeltas\\(\\) has parameter \\$data with no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Migration\\Service\\MigrationDataConverter\:\:filterDeltas\(\) has parameter \$data with no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Migration/Service/MigrationDataConverter.php - - message: "#^Method SwagMigrationAssistant\\\\Migration\\\\Service\\\\MigrationDataConverterInterface\\:\\:convert\\(\\) has parameter \\$data with no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Migration\\Service\\MigrationDataConverterInterface\:\:convert\(\) has parameter \$data with no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Migration/Service/MigrationDataConverterInterface.php - - message: "#^Class SwagMigrationAssistant\\\\Migration\\\\Setting\\\\GeneralSettingCollection extends generic class Shopware\\\\Core\\\\Framework\\\\DataAbstractionLayer\\\\EntityCollection but does not specify its types\\: TElement$#" + message: '#^Class SwagMigrationAssistant\\Migration\\Setting\\GeneralSettingCollection extends generic class Shopware\\Core\\Framework\\DataAbstractionLayer\\EntityCollection but does not specify its types\: TElement$#' + identifier: missingType.generics count: 1 path: src/Migration/Setting/GeneralSettingCollection.php - - message: "#^swag_migration_general_setting\\.selectedConnection association has a configured autoload\\=\\=\\=true, this is forbidden for platform integrations$#" + message: '#^swag_migration_general_setting\.selectedConnection association has a configured autoload\=\=\=true, this is forbidden for platform integrations$#' + identifier: shopware.associationAutoload count: 1 path: src/Migration/Setting/GeneralSettingDefinition.php - - message: "#^Method SwagMigrationAssistant\\\\Migration\\\\Writer\\\\TranslationWriter\\:\\:writeData\\(\\) has parameter \\$data with no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Migration\\Writer\\TranslationWriter\:\:writeData\(\) has parameter \$data with no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Migration/Writer/TranslationWriter.php - - message: "#^Method SwagMigrationAssistant\\\\Migration\\\\Writer\\\\TranslationWriter\\:\\:writeData\\(\\) return type has no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Migration\\Writer\\TranslationWriter\:\:writeData\(\) return type has no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Migration/Writer/TranslationWriter.php - - message: "#^Method SwagMigrationAssistant\\\\Migration\\\\Writer\\\\WriterInterface\\:\\:writeData\\(\\) has parameter \\$data with no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Migration\\Writer\\WriterInterface\:\:writeData\(\) has parameter \$data with no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Migration/Writer/WriterInterface.php - - message: "#^Method SwagMigrationAssistant\\\\Migration\\\\Writer\\\\WriterInterface\\:\\:writeData\\(\\) return type has no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Migration\\Writer\\WriterInterface\:\:writeData\(\) return type has no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Migration/Writer/WriterInterface.php - - message: "#^Method SwagMigrationAssistant\\\\Profile\\\\Shopware\\\\Converter\\\\CurrencyConverter\\:\\:getCurrencyTranslation\\(\\) has parameter \\$currency with no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Profile\\Shopware\\Converter\\CurrencyConverter\:\:getCurrencyTranslation\(\) has parameter \$currency with no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Profile/Shopware/Converter/CurrencyConverter.php - - message: "#^Method SwagMigrationAssistant\\\\Profile\\\\Shopware\\\\Converter\\\\CurrencyConverter\\:\\:getCurrencyTranslation\\(\\) has parameter \\$data with no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Profile\\Shopware\\Converter\\CurrencyConverter\:\:getCurrencyTranslation\(\) has parameter \$data with no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Profile/Shopware/Converter/CurrencyConverter.php - - message: "#^Method SwagMigrationAssistant\\\\Profile\\\\Shopware\\\\Converter\\\\CustomerGroupConverter\\:\\:getCustomerGroupTranslation\\(\\) has parameter \\$customerGroup with no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Profile\\Shopware\\Converter\\CustomerGroupConverter\:\:getCustomerGroupTranslation\(\) has parameter \$customerGroup with no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Profile/Shopware/Converter/CustomerGroupConverter.php - - message: "#^Method SwagMigrationAssistant\\\\Profile\\\\Shopware\\\\Converter\\\\CustomerGroupConverter\\:\\:getCustomerGroupTranslation\\(\\) has parameter \\$data with no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Profile\\Shopware\\Converter\\CustomerGroupConverter\:\:getCustomerGroupTranslation\(\) has parameter \$data with no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Profile/Shopware/Converter/CustomerGroupConverter.php - - message: "#^Method SwagMigrationAssistant\\\\Profile\\\\Shopware\\\\Converter\\\\MediaConverter\\:\\:getMediaTranslation\\(\\) has parameter \\$data with no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Profile\\Shopware\\Converter\\MediaConverter\:\:getMediaTranslation\(\) has parameter \$data with no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Profile/Shopware/Converter/MediaConverter.php - - message: "#^Method SwagMigrationAssistant\\\\Profile\\\\Shopware\\\\Converter\\\\MediaConverter\\:\\:getMediaTranslation\\(\\) has parameter \\$media with no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Profile\\Shopware\\Converter\\MediaConverter\:\:getMediaTranslation\(\) has parameter \$media with no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Profile/Shopware/Converter/MediaConverter.php - - message: "#^Method SwagMigrationAssistant\\\\Profile\\\\Shopware\\\\Converter\\\\MediaFolderConverter\\:\\:getConfiguration\\(\\) has parameter \\$setting with no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Profile\\Shopware\\Converter\\MediaFolderConverter\:\:getConfiguration\(\) has parameter \$setting with no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Profile/Shopware/Converter/MediaFolderConverter.php - - message: "#^Method SwagMigrationAssistant\\\\Profile\\\\Shopware\\\\Converter\\\\MediaFolderConverter\\:\\:getConfiguration\\(\\) return type has no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Profile\\Shopware\\Converter\\MediaFolderConverter\:\:getConfiguration\(\) return type has no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Profile/Shopware/Converter/MediaFolderConverter.php - - message: "#^Call to an undefined method Shopware\\\\Core\\\\Framework\\\\DataAbstractionLayer\\\\Entity\\:\\:getLanguageId\\(\\)\\.$#" + message: '#^Call to an undefined method Shopware\\Core\\Framework\\DataAbstractionLayer\\Entity\:\:getLanguageId\(\)\.$#' + identifier: method.notFound count: 1 path: src/Profile/Shopware/Converter/SalesChannelConverter.php - - message: "#^Method SwagMigrationAssistant\\\\Profile\\\\Shopware\\\\Converter\\\\SalesChannelConverter\\:\\:__construct\\(\\) has parameter \\$languagePackRepo with generic class Shopware\\\\Core\\\\Framework\\\\DataAbstractionLayer\\\\EntityRepository but does not specify its types\\: TEntityCollection$#" + message: '#^Method SwagMigrationAssistant\\Profile\\Shopware\\Converter\\SalesChannelConverter\:\:__construct\(\) has parameter \$languagePackRepo with generic class Shopware\\Core\\Framework\\DataAbstractionLayer\\EntityRepository but does not specify its types\: TEntityCollection$#' + identifier: missingType.generics count: 1 path: src/Profile/Shopware/Converter/SalesChannelConverter.php - - message: "#^Method SwagMigrationAssistant\\\\Profile\\\\Shopware\\\\Gateway\\\\Api\\\\Reader\\\\TableCountReader\\:\\:logExceptions\\(\\) has parameter \\$exceptionArray with no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Profile\\Shopware\\Gateway\\Api\\Reader\\TableCountReader\:\:logExceptions\(\) has parameter \$exceptionArray with no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Profile/Shopware/Gateway/Api/Reader/TableCountReader.php - - message: "#^Method SwagMigrationAssistant\\\\Profile\\\\Shopware\\\\Gateway\\\\Api\\\\Reader\\\\TableCountReader\\:\\:prepareTotals\\(\\) has parameter \\$result with no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Profile\\Shopware\\Gateway\\Api\\Reader\\TableCountReader\:\:prepareTotals\(\) has parameter \$result with no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Profile/Shopware/Gateway/Api/Reader/TableCountReader.php - - message: "#^Method SwagMigrationAssistant\\\\Profile\\\\Shopware\\\\Gateway\\\\Api\\\\Reader\\\\TableCountReader\\:\\:readTotals\\(\\) return type has no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Profile\\Shopware\\Gateway\\Api\\Reader\\TableCountReader\:\:readTotals\(\) return type has no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Profile/Shopware/Gateway/Api/Reader/TableCountReader.php - - message: "#^Method SwagMigrationAssistant\\\\Profile\\\\Shopware\\\\Gateway\\\\Api\\\\Reader\\\\TableReader\\:\\:read\\(\\) has parameter \\$filter with no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Profile\\Shopware\\Gateway\\Api\\Reader\\TableReader\:\:read\(\) has parameter \$filter with no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Profile/Shopware/Gateway/Api/Reader/TableReader.php - - message: "#^Method SwagMigrationAssistant\\\\Profile\\\\Shopware\\\\Gateway\\\\Api\\\\Reader\\\\TableReader\\:\\:read\\(\\) return type has no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Profile\\Shopware\\Gateway\\Api\\Reader\\TableReader\:\:read\(\) return type has no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Profile/Shopware/Gateway/Api/Reader/TableReader.php - - message: "#^Method SwagMigrationAssistant\\\\Profile\\\\Shopware\\\\Gateway\\\\Api\\\\ShopwareApiGateway\\:\\:readTable\\(\\) has parameter \\$filter with no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Profile\\Shopware\\Gateway\\Api\\ShopwareApiGateway\:\:readTable\(\) has parameter \$filter with no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Profile/Shopware/Gateway/Api/ShopwareApiGateway.php - - message: "#^Method SwagMigrationAssistant\\\\Profile\\\\Shopware\\\\Gateway\\\\Api\\\\ShopwareApiGateway\\:\\:readTable\\(\\) return type has no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Profile\\Shopware\\Gateway\\Api\\ShopwareApiGateway\:\:readTable\(\) return type has no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Profile/Shopware/Gateway/Api/ShopwareApiGateway.php - - message: "#^Method SwagMigrationAssistant\\\\Profile\\\\Shopware\\\\Gateway\\\\Local\\\\Reader\\\\CategoryReader\\:\\:fetchData\\(\\) return type has no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Profile\\Shopware\\Gateway\\Local\\Reader\\CategoryReader\:\:fetchData\(\) return type has no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Profile/Shopware/Gateway/Local/Reader/CategoryReader.php - - message: "#^Method SwagMigrationAssistant\\\\Profile\\\\Shopware\\\\Gateway\\\\Local\\\\Reader\\\\CategoryReader\\:\\:fetchMainCategoryLocales\\(\\) return type has no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Profile\\Shopware\\Gateway\\Local\\Reader\\CategoryReader\:\:fetchMainCategoryLocales\(\) return type has no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Profile/Shopware/Gateway/Local/Reader/CategoryReader.php - - message: "#^Method SwagMigrationAssistant\\\\Profile\\\\Shopware\\\\Gateway\\\\Local\\\\Reader\\\\CategoryReader\\:\\:generateAllLocales\\(\\) has parameter \\$categories with no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Profile\\Shopware\\Gateway\\Local\\Reader\\CategoryReader\:\:generateAllLocales\(\) has parameter \$categories with no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Profile/Shopware/Gateway/Local/Reader/CategoryReader.php - - message: "#^Method SwagMigrationAssistant\\\\Profile\\\\Shopware\\\\Gateway\\\\Local\\\\Reader\\\\CategoryReader\\:\\:generateAllLocales\\(\\) has parameter \\$mainCategoryLocales with no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Profile\\Shopware\\Gateway\\Local\\Reader\\CategoryReader\:\:generateAllLocales\(\) has parameter \$mainCategoryLocales with no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Profile/Shopware/Gateway/Local/Reader/CategoryReader.php - - message: "#^Method SwagMigrationAssistant\\\\Profile\\\\Shopware\\\\Gateway\\\\Local\\\\Reader\\\\CategoryReader\\:\\:generateAllLocales\\(\\) return type has no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Profile\\Shopware\\Gateway\\Local\\Reader\\CategoryReader\:\:generateAllLocales\(\) return type has no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Profile/Shopware/Gateway/Local/Reader/CategoryReader.php - - message: "#^Method SwagMigrationAssistant\\\\Profile\\\\Shopware\\\\Gateway\\\\Local\\\\Reader\\\\CategoryReader\\:\\:getIgnoredCategories\\(\\) return type has no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Profile\\Shopware\\Gateway\\Local\\Reader\\CategoryReader\:\:getIgnoredCategories\(\) return type has no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Profile/Shopware/Gateway/Local/Reader/CategoryReader.php - - message: "#^Method SwagMigrationAssistant\\\\Profile\\\\Shopware\\\\Gateway\\\\Local\\\\Reader\\\\CrossSellingReader\\:\\:enrichWithPositionData\\(\\) has parameter \\$fetchedCrossSelling with no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Profile\\Shopware\\Gateway\\Local\\Reader\\CrossSellingReader\:\:enrichWithPositionData\(\) has parameter \$fetchedCrossSelling with no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Profile/Shopware/Gateway/Local/Reader/CrossSellingReader.php - - message: "#^Method SwagMigrationAssistant\\\\Profile\\\\Shopware\\\\Gateway\\\\Local\\\\Reader\\\\CrossSellingReader\\:\\:fetchData\\(\\) return type has no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Profile\\Shopware\\Gateway\\Local\\Reader\\CrossSellingReader\:\:fetchData\(\) return type has no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Profile/Shopware/Gateway/Local/Reader/CrossSellingReader.php - - message: "#^Method SwagMigrationAssistant\\\\Profile\\\\Shopware\\\\Gateway\\\\Local\\\\Reader\\\\CurrencyReader\\:\\:fetchData\\(\\) return type has no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Profile\\Shopware\\Gateway\\Local\\Reader\\CurrencyReader\:\:fetchData\(\) return type has no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Profile/Shopware/Gateway/Local/Reader/CurrencyReader.php - - message: "#^Method SwagMigrationAssistant\\\\Profile\\\\Shopware\\\\Gateway\\\\Local\\\\Reader\\\\CustomerGroupReader\\:\\:fetchCustomerGroupDiscounts\\(\\) has parameter \\$groupIds with no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Profile\\Shopware\\Gateway\\Local\\Reader\\CustomerGroupReader\:\:fetchCustomerGroupDiscounts\(\) has parameter \$groupIds with no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Profile/Shopware/Gateway/Local/Reader/CustomerGroupReader.php - - message: "#^Method SwagMigrationAssistant\\\\Profile\\\\Shopware\\\\Gateway\\\\Local\\\\Reader\\\\CustomerGroupReader\\:\\:fetchCustomerGroupDiscounts\\(\\) return type has no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Profile\\Shopware\\Gateway\\Local\\Reader\\CustomerGroupReader\:\:fetchCustomerGroupDiscounts\(\) return type has no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Profile/Shopware/Gateway/Local/Reader/CustomerGroupReader.php - - message: "#^Method SwagMigrationAssistant\\\\Profile\\\\Shopware\\\\Gateway\\\\Local\\\\Reader\\\\CustomerGroupReader\\:\\:fetchCustomerGroups\\(\\) return type has no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Profile\\Shopware\\Gateway\\Local\\Reader\\CustomerGroupReader\:\:fetchCustomerGroups\(\) return type has no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Profile/Shopware/Gateway/Local/Reader/CustomerGroupReader.php - - message: "#^Method SwagMigrationAssistant\\\\Profile\\\\Shopware\\\\Gateway\\\\Local\\\\Reader\\\\LanguageReader\\:\\:appendAssociatedData\\(\\) has parameter \\$locales with no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Profile\\Shopware\\Gateway\\Local\\Reader\\LanguageReader\:\:appendAssociatedData\(\) has parameter \$locales with no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Profile/Shopware/Gateway/Local/Reader/LanguageReader.php - - message: "#^Method SwagMigrationAssistant\\\\Profile\\\\Shopware\\\\Gateway\\\\Local\\\\Reader\\\\LanguageReader\\:\\:appendAssociatedData\\(\\) return type has no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Profile\\Shopware\\Gateway\\Local\\Reader\\LanguageReader\:\:appendAssociatedData\(\) return type has no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Profile/Shopware/Gateway/Local/Reader/LanguageReader.php - - message: "#^Method SwagMigrationAssistant\\\\Profile\\\\Shopware\\\\Gateway\\\\Local\\\\Reader\\\\LanguageReader\\:\\:fetchLocales\\(\\) has parameter \\$fetchedShopLocaleIds with no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Profile\\Shopware\\Gateway\\Local\\Reader\\LanguageReader\:\:fetchLocales\(\) has parameter \$fetchedShopLocaleIds with no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Profile/Shopware/Gateway/Local/Reader/LanguageReader.php - - message: "#^Method SwagMigrationAssistant\\\\Profile\\\\Shopware\\\\Gateway\\\\Local\\\\Reader\\\\LanguageReader\\:\\:fetchLocales\\(\\) return type has no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Profile\\Shopware\\Gateway\\Local\\Reader\\LanguageReader\:\:fetchLocales\(\) return type has no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Profile/Shopware/Gateway/Local/Reader/LanguageReader.php - - message: "#^Method SwagMigrationAssistant\\\\Profile\\\\Shopware\\\\Gateway\\\\Local\\\\Reader\\\\LanguageReader\\:\\:fetchShopLocaleIds\\(\\) return type has no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Profile\\Shopware\\Gateway\\Local\\Reader\\LanguageReader\:\:fetchShopLocaleIds\(\) return type has no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Profile/Shopware/Gateway/Local/Reader/LanguageReader.php - - message: "#^Method SwagMigrationAssistant\\\\Profile\\\\Shopware\\\\Gateway\\\\Local\\\\Reader\\\\LanguageReader\\:\\:fetchTranslations\\(\\) has parameter \\$locales with no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Profile\\Shopware\\Gateway\\Local\\Reader\\LanguageReader\:\:fetchTranslations\(\) has parameter \$locales with no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Profile/Shopware/Gateway/Local/Reader/LanguageReader.php - - message: "#^Method SwagMigrationAssistant\\\\Profile\\\\Shopware\\\\Gateway\\\\Local\\\\Reader\\\\LanguageReader\\:\\:fetchTranslations\\(\\) return type has no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Profile\\Shopware\\Gateway\\Local\\Reader\\LanguageReader\:\:fetchTranslations\(\) return type has no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Profile/Shopware/Gateway/Local/Reader/LanguageReader.php - - message: "#^Method SwagMigrationAssistant\\\\Profile\\\\Shopware\\\\Gateway\\\\Local\\\\Reader\\\\MainVariantRelationReader\\:\\:fetchMainVariantRelations\\(\\) return type has no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Profile\\Shopware\\Gateway\\Local\\Reader\\MainVariantRelationReader\:\:fetchMainVariantRelations\(\) return type has no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Profile/Shopware/Gateway/Local/Reader/MainVariantRelationReader.php - - message: "#^Method SwagMigrationAssistant\\\\Profile\\\\Shopware\\\\Gateway\\\\Local\\\\Reader\\\\MediaAlbumReader\\:\\:fetchAlbums\\(\\) return type has no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Profile\\Shopware\\Gateway\\Local\\Reader\\MediaAlbumReader\:\:fetchAlbums\(\) return type has no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Profile/Shopware/Gateway/Local/Reader/MediaAlbumReader.php - - message: "#^Method SwagMigrationAssistant\\\\Profile\\\\Shopware\\\\Gateway\\\\Local\\\\Reader\\\\MediaAlbumReader\\:\\:getChildAlbums\\(\\) has parameter \\$mediaAlbums with no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Profile\\Shopware\\Gateway\\Local\\Reader\\MediaAlbumReader\:\:getChildAlbums\(\) has parameter \$mediaAlbums with no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Profile/Shopware/Gateway/Local/Reader/MediaAlbumReader.php - - message: "#^Method SwagMigrationAssistant\\\\Profile\\\\Shopware\\\\Gateway\\\\Local\\\\Reader\\\\MediaAlbumReader\\:\\:getChildAlbums\\(\\) return type has no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Profile\\Shopware\\Gateway\\Local\\Reader\\MediaAlbumReader\:\:getChildAlbums\(\) return type has no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Profile/Shopware/Gateway/Local/Reader/MediaAlbumReader.php - - message: "#^Method SwagMigrationAssistant\\\\Profile\\\\Shopware\\\\Gateway\\\\Local\\\\Reader\\\\MediaAlbumReader\\:\\:prepareMediaAlbums\\(\\) has parameter \\$mediaAlbums with no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Profile\\Shopware\\Gateway\\Local\\Reader\\MediaAlbumReader\:\:prepareMediaAlbums\(\) has parameter \$mediaAlbums with no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Profile/Shopware/Gateway/Local/Reader/MediaAlbumReader.php - - message: "#^Method SwagMigrationAssistant\\\\Profile\\\\Shopware\\\\Gateway\\\\Local\\\\Reader\\\\MediaAlbumReader\\:\\:prepareMediaAlbums\\(\\) return type has no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Profile\\Shopware\\Gateway\\Local\\Reader\\MediaAlbumReader\:\:prepareMediaAlbums\(\) return type has no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Profile/Shopware/Gateway/Local/Reader/MediaAlbumReader.php - - message: "#^Method SwagMigrationAssistant\\\\Profile\\\\Shopware\\\\Gateway\\\\Local\\\\Reader\\\\MediaReader\\:\\:fetchData\\(\\) return type has no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Profile\\Shopware\\Gateway\\Local\\Reader\\MediaReader\:\:fetchData\(\) return type has no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Profile/Shopware/Gateway/Local/Reader/MediaReader.php - - message: "#^Method SwagMigrationAssistant\\\\Profile\\\\Shopware\\\\Gateway\\\\Local\\\\Reader\\\\MediaReader\\:\\:prepareMedia\\(\\) has parameter \\$media with no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Profile\\Shopware\\Gateway\\Local\\Reader\\MediaReader\:\:prepareMedia\(\) has parameter \$media with no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Profile/Shopware/Gateway/Local/Reader/MediaReader.php - - message: "#^Method SwagMigrationAssistant\\\\Profile\\\\Shopware\\\\Gateway\\\\Local\\\\Reader\\\\MediaReader\\:\\:prepareMedia\\(\\) return type has no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Profile\\Shopware\\Gateway\\Local\\Reader\\MediaReader\:\:prepareMedia\(\) return type has no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Profile/Shopware/Gateway/Local/Reader/MediaReader.php - - message: "#^Method SwagMigrationAssistant\\\\Profile\\\\Shopware\\\\Gateway\\\\Local\\\\Reader\\\\NewsletterRecipientReader\\:\\:addShopAndLocaleByCustomer\\(\\) has parameter \\$item with no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Profile\\Shopware\\Gateway\\Local\\Reader\\NewsletterRecipientReader\:\:addShopAndLocaleByCustomer\(\) has parameter \$item with no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Profile/Shopware/Gateway/Local/Reader/NewsletterRecipientReader.php - - message: "#^Method SwagMigrationAssistant\\\\Profile\\\\Shopware\\\\Gateway\\\\Local\\\\Reader\\\\NewsletterRecipientReader\\:\\:addShopAndLocaleByCustomer\\(\\) has parameter \\$shop with no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Profile\\Shopware\\Gateway\\Local\\Reader\\NewsletterRecipientReader\:\:addShopAndLocaleByCustomer\(\) has parameter \$shop with no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Profile/Shopware/Gateway/Local/Reader/NewsletterRecipientReader.php - - message: "#^Method SwagMigrationAssistant\\\\Profile\\\\Shopware\\\\Gateway\\\\Local\\\\Reader\\\\NewsletterRecipientReader\\:\\:addShopAndLocaleByGroupId\\(\\) has parameter \\$defaultShop with no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Profile\\Shopware\\Gateway\\Local\\Reader\\NewsletterRecipientReader\:\:addShopAndLocaleByGroupId\(\) has parameter \$defaultShop with no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Profile/Shopware/Gateway/Local/Reader/NewsletterRecipientReader.php - - message: "#^Method SwagMigrationAssistant\\\\Profile\\\\Shopware\\\\Gateway\\\\Local\\\\Reader\\\\NewsletterRecipientReader\\:\\:addShopAndLocaleByGroupId\\(\\) has parameter \\$item with no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Profile\\Shopware\\Gateway\\Local\\Reader\\NewsletterRecipientReader\:\:addShopAndLocaleByGroupId\(\) has parameter \$item with no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Profile/Shopware/Gateway/Local/Reader/NewsletterRecipientReader.php - - message: "#^Method SwagMigrationAssistant\\\\Profile\\\\Shopware\\\\Gateway\\\\Local\\\\Reader\\\\NewsletterRecipientReader\\:\\:addShopAndLocaleByGroupId\\(\\) has parameter \\$shops with no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Profile\\Shopware\\Gateway\\Local\\Reader\\NewsletterRecipientReader\:\:addShopAndLocaleByGroupId\(\) has parameter \$shops with no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Profile/Shopware/Gateway/Local/Reader/NewsletterRecipientReader.php - - message: "#^Method SwagMigrationAssistant\\\\Profile\\\\Shopware\\\\Gateway\\\\Local\\\\Reader\\\\NewsletterRecipientReader\\:\\:fetchData\\(\\) has parameter \\$ids with no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Profile\\Shopware\\Gateway\\Local\\Reader\\NewsletterRecipientReader\:\:fetchData\(\) has parameter \$ids with no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Profile/Shopware/Gateway/Local/Reader/NewsletterRecipientReader.php - - message: "#^Method SwagMigrationAssistant\\\\Profile\\\\Shopware\\\\Gateway\\\\Local\\\\Reader\\\\NewsletterRecipientReader\\:\\:fetchData\\(\\) return type has no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Profile\\Shopware\\Gateway\\Local\\Reader\\NewsletterRecipientReader\:\:fetchData\(\) return type has no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Profile/Shopware/Gateway/Local/Reader/NewsletterRecipientReader.php - - message: "#^Method SwagMigrationAssistant\\\\Profile\\\\Shopware\\\\Gateway\\\\Local\\\\Reader\\\\NewsletterRecipientReader\\:\\:getDefaultShopAndLocaleByGroupId\\(\\) return type has no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Profile\\Shopware\\Gateway\\Local\\Reader\\NewsletterRecipientReader\:\:getDefaultShopAndLocaleByGroupId\(\) return type has no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Profile/Shopware/Gateway/Local/Reader/NewsletterRecipientReader.php - - message: "#^Method SwagMigrationAssistant\\\\Profile\\\\Shopware\\\\Gateway\\\\Local\\\\Reader\\\\NewsletterRecipientReader\\:\\:getGroupedResult\\(\\) has parameter \\$shops with no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Profile\\Shopware\\Gateway\\Local\\Reader\\NewsletterRecipientReader\:\:getGroupedResult\(\) has parameter \$shops with no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Profile/Shopware/Gateway/Local/Reader/NewsletterRecipientReader.php - - message: "#^Method SwagMigrationAssistant\\\\Profile\\\\Shopware\\\\Gateway\\\\Local\\\\Reader\\\\NewsletterRecipientReader\\:\\:getGroupedResult\\(\\) return type has no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Profile\\Shopware\\Gateway\\Local\\Reader\\NewsletterRecipientReader\:\:getGroupedResult\(\) return type has no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Profile/Shopware/Gateway/Local/Reader/NewsletterRecipientReader.php - - message: "#^Method SwagMigrationAssistant\\\\Profile\\\\Shopware\\\\Gateway\\\\Local\\\\Reader\\\\NewsletterRecipientReader\\:\\:getShopsAndLocalesByCustomer\\(\\) has parameter \\$ids with no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Profile\\Shopware\\Gateway\\Local\\Reader\\NewsletterRecipientReader\:\:getShopsAndLocalesByCustomer\(\) has parameter \$ids with no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Profile/Shopware/Gateway/Local/Reader/NewsletterRecipientReader.php - - message: "#^Method SwagMigrationAssistant\\\\Profile\\\\Shopware\\\\Gateway\\\\Local\\\\Reader\\\\NewsletterRecipientReader\\:\\:getShopsAndLocalesByCustomer\\(\\) return type has no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Profile\\Shopware\\Gateway\\Local\\Reader\\NewsletterRecipientReader\:\:getShopsAndLocalesByCustomer\(\) return type has no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Profile/Shopware/Gateway/Local/Reader/NewsletterRecipientReader.php - - message: "#^Method SwagMigrationAssistant\\\\Profile\\\\Shopware\\\\Gateway\\\\Local\\\\Reader\\\\NewsletterRecipientReader\\:\\:getShopsAndLocalesByGroupId\\(\\) return type has no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Profile\\Shopware\\Gateway\\Local\\Reader\\NewsletterRecipientReader\:\:getShopsAndLocalesByGroupId\(\) return type has no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Profile/Shopware/Gateway/Local/Reader/NewsletterRecipientReader.php - - message: "#^Method SwagMigrationAssistant\\\\Profile\\\\Shopware\\\\Gateway\\\\Local\\\\Reader\\\\OrderDocumentReader\\:\\:fetchDocuments\\(\\) return type has no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Profile\\Shopware\\Gateway\\Local\\Reader\\OrderDocumentReader\:\:fetchDocuments\(\) return type has no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Profile/Shopware/Gateway/Local/Reader/OrderDocumentReader.php - - message: "#^Method SwagMigrationAssistant\\\\Profile\\\\Shopware\\\\Gateway\\\\Local\\\\Reader\\\\ProductOptionRelationReader\\:\\:fetchData\\(\\) return type has no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Profile\\Shopware\\Gateway\\Local\\Reader\\ProductOptionRelationReader\:\:fetchData\(\) return type has no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Profile/Shopware/Gateway/Local/Reader/ProductOptionRelationReader.php - - message: "#^Method SwagMigrationAssistant\\\\Profile\\\\Shopware\\\\Gateway\\\\Local\\\\Reader\\\\ProductPropertyRelationReader\\:\\:fetchData\\(\\) return type has no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Profile\\Shopware\\Gateway\\Local\\Reader\\ProductPropertyRelationReader\:\:fetchData\(\) return type has no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Profile/Shopware/Gateway/Local/Reader/ProductPropertyRelationReader.php - - message: "#^Method SwagMigrationAssistant\\\\Profile\\\\Shopware\\\\Gateway\\\\Local\\\\Reader\\\\ProductReviewReader\\:\\:fetchReviews\\(\\) return type has no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Profile\\Shopware\\Gateway\\Local\\Reader\\ProductReviewReader\:\:fetchReviews\(\) return type has no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Profile/Shopware/Gateway/Local/Reader/ProductReviewReader.php - - message: "#^Method SwagMigrationAssistant\\\\Profile\\\\Shopware\\\\Gateway\\\\Local\\\\Reader\\\\PromotionReader\\:\\:fetchIndividualCodes\\(\\) has parameter \\$ids with no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Profile\\Shopware\\Gateway\\Local\\Reader\\PromotionReader\:\:fetchIndividualCodes\(\) has parameter \$ids with no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Profile/Shopware/Gateway/Local/Reader/PromotionReader.php - - message: "#^Method SwagMigrationAssistant\\\\Profile\\\\Shopware\\\\Gateway\\\\Local\\\\Reader\\\\PromotionReader\\:\\:fetchIndividualCodes\\(\\) return type has no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Profile\\Shopware\\Gateway\\Local\\Reader\\PromotionReader\:\:fetchIndividualCodes\(\) return type has no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Profile/Shopware/Gateway/Local/Reader/PromotionReader.php - - message: "#^Method SwagMigrationAssistant\\\\Profile\\\\Shopware\\\\Gateway\\\\Local\\\\Reader\\\\PromotionReader\\:\\:fetchPromotions\\(\\) has parameter \\$ids with no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Profile\\Shopware\\Gateway\\Local\\Reader\\PromotionReader\:\:fetchPromotions\(\) has parameter \$ids with no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Profile/Shopware/Gateway/Local/Reader/PromotionReader.php - - message: "#^Method SwagMigrationAssistant\\\\Profile\\\\Shopware\\\\Gateway\\\\Local\\\\Reader\\\\PromotionReader\\:\\:fetchPromotions\\(\\) return type has no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Profile\\Shopware\\Gateway\\Local\\Reader\\PromotionReader\:\:fetchPromotions\(\) return type has no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Profile/Shopware/Gateway/Local/Reader/PromotionReader.php - - message: "#^Method SwagMigrationAssistant\\\\Profile\\\\Shopware\\\\Gateway\\\\Local\\\\Reader\\\\PropertyGroupOptionReader\\:\\:fetchData\\(\\) return type has no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Profile\\Shopware\\Gateway\\Local\\Reader\\PropertyGroupOptionReader\:\:fetchData\(\) return type has no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Profile/Shopware/Gateway/Local/Reader/PropertyGroupOptionReader.php - - message: "#^Method SwagMigrationAssistant\\\\Profile\\\\Shopware\\\\Gateway\\\\Local\\\\Reader\\\\ShippingMethodReader\\:\\:fetchExcludedCategories\\(\\) has parameter \\$shippingMethodIds with no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Profile\\Shopware\\Gateway\\Local\\Reader\\ShippingMethodReader\:\:fetchExcludedCategories\(\) has parameter \$shippingMethodIds with no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Profile/Shopware/Gateway/Local/Reader/ShippingMethodReader.php - - message: "#^Method SwagMigrationAssistant\\\\Profile\\\\Shopware\\\\Gateway\\\\Local\\\\Reader\\\\ShippingMethodReader\\:\\:fetchExcludedCategories\\(\\) return type has no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Profile\\Shopware\\Gateway\\Local\\Reader\\ShippingMethodReader\:\:fetchExcludedCategories\(\) return type has no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Profile/Shopware/Gateway/Local/Reader/ShippingMethodReader.php - - message: "#^Method SwagMigrationAssistant\\\\Profile\\\\Shopware\\\\Gateway\\\\Local\\\\Reader\\\\ShippingMethodReader\\:\\:fetchPaymentMethods\\(\\) has parameter \\$shippingMethodIds with no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Profile\\Shopware\\Gateway\\Local\\Reader\\ShippingMethodReader\:\:fetchPaymentMethods\(\) has parameter \$shippingMethodIds with no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Profile/Shopware/Gateway/Local/Reader/ShippingMethodReader.php - - message: "#^Method SwagMigrationAssistant\\\\Profile\\\\Shopware\\\\Gateway\\\\Local\\\\Reader\\\\ShippingMethodReader\\:\\:fetchPaymentMethods\\(\\) return type has no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Profile\\Shopware\\Gateway\\Local\\Reader\\ShippingMethodReader\:\:fetchPaymentMethods\(\) return type has no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Profile/Shopware/Gateway/Local/Reader/ShippingMethodReader.php - - message: "#^Method SwagMigrationAssistant\\\\Profile\\\\Shopware\\\\Gateway\\\\Local\\\\Reader\\\\ShippingMethodReader\\:\\:fetchShippingCosts\\(\\) has parameter \\$shippingMethodIds with no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Profile\\Shopware\\Gateway\\Local\\Reader\\ShippingMethodReader\:\:fetchShippingCosts\(\) has parameter \$shippingMethodIds with no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Profile/Shopware/Gateway/Local/Reader/ShippingMethodReader.php - - message: "#^Method SwagMigrationAssistant\\\\Profile\\\\Shopware\\\\Gateway\\\\Local\\\\Reader\\\\ShippingMethodReader\\:\\:fetchShippingCosts\\(\\) return type has no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Profile\\Shopware\\Gateway\\Local\\Reader\\ShippingMethodReader\:\:fetchShippingCosts\(\) return type has no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Profile/Shopware/Gateway/Local/Reader/ShippingMethodReader.php - - message: "#^Method SwagMigrationAssistant\\\\Profile\\\\Shopware\\\\Gateway\\\\Local\\\\Reader\\\\ShippingMethodReader\\:\\:fetchShippingCountries\\(\\) has parameter \\$shippingMethodIds with no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Profile\\Shopware\\Gateway\\Local\\Reader\\ShippingMethodReader\:\:fetchShippingCountries\(\) has parameter \$shippingMethodIds with no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Profile/Shopware/Gateway/Local/Reader/ShippingMethodReader.php - - message: "#^Method SwagMigrationAssistant\\\\Profile\\\\Shopware\\\\Gateway\\\\Local\\\\Reader\\\\ShippingMethodReader\\:\\:fetchShippingCountries\\(\\) return type has no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Profile\\Shopware\\Gateway\\Local\\Reader\\ShippingMethodReader\:\:fetchShippingCountries\(\) return type has no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Profile/Shopware/Gateway/Local/Reader/ShippingMethodReader.php - - message: "#^Method SwagMigrationAssistant\\\\Profile\\\\Shopware\\\\Gateway\\\\Local\\\\Reader\\\\ShippingMethodReader\\:\\:fetchShippingMethods\\(\\) has parameter \\$shippingMethodIds with no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Profile\\Shopware\\Gateway\\Local\\Reader\\ShippingMethodReader\:\:fetchShippingMethods\(\) has parameter \$shippingMethodIds with no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Profile/Shopware/Gateway/Local/Reader/ShippingMethodReader.php - - message: "#^Method SwagMigrationAssistant\\\\Profile\\\\Shopware\\\\Gateway\\\\Local\\\\Reader\\\\ShippingMethodReader\\:\\:fetchShippingMethods\\(\\) return type has no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Profile\\Shopware\\Gateway\\Local\\Reader\\ShippingMethodReader\:\:fetchShippingMethods\(\) return type has no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Profile/Shopware/Gateway/Local/Reader/ShippingMethodReader.php - - message: "#^Method SwagMigrationAssistant\\\\Profile\\\\Shopware\\\\Gateway\\\\Local\\\\Reader\\\\TableReader\\:\\:read\\(\\) has parameter \\$filter with no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Profile\\Shopware\\Gateway\\Local\\Reader\\TableReader\:\:read\(\) has parameter \$filter with no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Profile/Shopware/Gateway/Local/Reader/TableReader.php - - message: "#^Method SwagMigrationAssistant\\\\Profile\\\\Shopware\\\\Gateway\\\\Local\\\\Reader\\\\TableReader\\:\\:read\\(\\) return type has no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Profile\\Shopware\\Gateway\\Local\\Reader\\TableReader\:\:read\(\) return type has no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Profile/Shopware/Gateway/Local/Reader/TableReader.php - - message: "#^Method SwagMigrationAssistant\\\\Profile\\\\Shopware\\\\Gateway\\\\Local\\\\Reader\\\\TranslationReader\\:\\:fetchTranslations\\(\\) return type has no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Profile\\Shopware\\Gateway\\Local\\Reader\\TranslationReader\:\:fetchTranslations\(\) return type has no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Profile/Shopware/Gateway/Local/Reader/TranslationReader.php - - message: "#^Method SwagMigrationAssistant\\\\Profile\\\\Shopware\\\\Gateway\\\\Local\\\\ShopwareLocalGateway\\:\\:readTable\\(\\) has parameter \\$filter with no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Profile\\Shopware\\Gateway\\Local\\ShopwareLocalGateway\:\:readTable\(\) has parameter \$filter with no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Profile/Shopware/Gateway/Local/ShopwareLocalGateway.php - - message: "#^Method SwagMigrationAssistant\\\\Profile\\\\Shopware\\\\Gateway\\\\Local\\\\ShopwareLocalGateway\\:\\:readTable\\(\\) return type has no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Profile\\Shopware\\Gateway\\Local\\ShopwareLocalGateway\:\:readTable\(\) return type has no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Profile/Shopware/Gateway/Local/ShopwareLocalGateway.php - - message: "#^Method SwagMigrationAssistant\\\\Profile\\\\Shopware\\\\Gateway\\\\ShopwareGatewayInterface\\:\\:readTable\\(\\) has parameter \\$filter with no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Profile\\Shopware\\Gateway\\ShopwareGatewayInterface\:\:readTable\(\) has parameter \$filter with no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Profile/Shopware/Gateway/ShopwareGatewayInterface.php - - message: "#^Method SwagMigrationAssistant\\\\Profile\\\\Shopware\\\\Gateway\\\\ShopwareGatewayInterface\\:\\:readTable\\(\\) return type has no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Profile\\Shopware\\Gateway\\ShopwareGatewayInterface\:\:readTable\(\) return type has no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Profile/Shopware/Gateway/ShopwareGatewayInterface.php - - message: "#^Method SwagMigrationAssistant\\\\Profile\\\\Shopware\\\\Gateway\\\\TableCountReaderInterface\\:\\:readTotals\\(\\) return type has no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Profile\\Shopware\\Gateway\\TableCountReaderInterface\:\:readTotals\(\) return type has no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Profile/Shopware/Gateway/TableCountReaderInterface.php - - message: "#^Method SwagMigrationAssistant\\\\Profile\\\\Shopware\\\\Gateway\\\\TableReaderInterface\\:\\:read\\(\\) has parameter \\$filter with no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Profile\\Shopware\\Gateway\\TableReaderInterface\:\:read\(\) has parameter \$filter with no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Profile/Shopware/Gateway/TableReaderInterface.php - - message: "#^Method SwagMigrationAssistant\\\\Profile\\\\Shopware\\\\Gateway\\\\TableReaderInterface\\:\\:read\\(\\) return type has no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Profile\\Shopware\\Gateway\\TableReaderInterface\:\:read\(\) return type has no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Profile/Shopware/Gateway/TableReaderInterface.php - - message: "#^Method SwagMigrationAssistant\\\\Profile\\\\Shopware\\\\Media\\\\LocalOrderDocumentProcessor\\:\\:copyMediaFiles\\(\\) has parameter \\$media with no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Profile\\Shopware\\Media\\LocalOrderDocumentProcessor\:\:copyMediaFiles\(\) has parameter \$media with no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Profile/Shopware/Media/LocalOrderDocumentProcessor.php - - message: "#^Method SwagMigrationAssistant\\\\Profile\\\\Shopware\\\\Media\\\\LocalOrderDocumentProcessor\\:\\:persistFileToMedia\\(\\) has parameter \\$media with no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Profile\\Shopware\\Media\\LocalOrderDocumentProcessor\:\:persistFileToMedia\(\) has parameter \$media with no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Profile/Shopware/Media/LocalOrderDocumentProcessor.php - - message: "#^Parameter \\#1 \\$blob of method Shopware\\\\Core\\\\Content\\\\Media\\\\MediaService\\:\\:saveFile\\(\\) expects string, string\\|false given\\.$#" + message: '#^Parameter \#1 \$blob of method Shopware\\Core\\Content\\Media\\MediaService\:\:saveFile\(\) expects string, string\|false given\.$#' + identifier: argument.type count: 3 path: src/Profile/Shopware/Media/LocalOrderDocumentProcessor.php - - message: "#^Parameter \\#3 \\$contentType of method Shopware\\\\Core\\\\Content\\\\Media\\\\MediaService\\:\\:saveFile\\(\\) expects string, string\\|false given\\.$#" + message: '#^Parameter \#3 \$contentType of method Shopware\\Core\\Content\\Media\\MediaService\:\:saveFile\(\) expects string, string\|false given\.$#' + identifier: argument.type count: 3 path: src/Profile/Shopware/Media/LocalOrderDocumentProcessor.php - - message: "#^Parameter \\#4 \\$filename of method Shopware\\\\Core\\\\Content\\\\Media\\\\MediaService\\:\\:saveFile\\(\\) expects string, string\\|null given\\.$#" + message: '#^Parameter \#4 \$filename of method Shopware\\Core\\Content\\Media\\MediaService\:\:saveFile\(\) expects string, string\|null given\.$#' + identifier: argument.type count: 1 path: src/Profile/Shopware/Media/LocalOrderDocumentProcessor.php - - message: "#^Method SwagMigrationAssistant\\\\Profile\\\\Shopware\\\\Media\\\\LocalProductDownloadProcessor\\:\\:copyMediaFiles\\(\\) has parameter \\$media with no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Profile\\Shopware\\Media\\LocalProductDownloadProcessor\:\:copyMediaFiles\(\) has parameter \$media with no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Profile/Shopware/Media/LocalProductDownloadProcessor.php - - message: "#^Method SwagMigrationAssistant\\\\Profile\\\\Shopware\\\\Media\\\\LocalProductDownloadProcessor\\:\\:persistFileToMedia\\(\\) has parameter \\$media with no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Profile\\Shopware\\Media\\LocalProductDownloadProcessor\:\:persistFileToMedia\(\) has parameter \$media with no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Profile/Shopware/Media/LocalProductDownloadProcessor.php - - message: "#^Method SwagMigrationAssistant\\\\Profile\\\\Shopware6\\\\Converter\\\\CmsPageConverter\\:\\:processSubentities\\(\\) has parameter \\$sections with no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Profile\\Shopware6\\Converter\\CmsPageConverter\:\:processSubentities\(\) has parameter \$sections with no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Profile/Shopware6/Converter/CmsPageConverter.php - - message: "#^Method SwagMigrationAssistant\\\\Profile\\\\Shopware6\\\\Converter\\\\CmsPageConverter\\:\\:updateTranslations\\(\\) has parameter \\$converted with no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Profile\\Shopware6\\Converter\\CmsPageConverter\:\:updateTranslations\(\) has parameter \$converted with no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Profile/Shopware6/Converter/CmsPageConverter.php - - message: "#^Method SwagMigrationAssistant\\\\Profile\\\\Shopware6\\\\Converter\\\\NumberRangeConverter\\:\\:checkForExistingNumberRange\\(\\) has parameter \\$converted with no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Profile\\Shopware6\\Converter\\NumberRangeConverter\:\:checkForExistingNumberRange\(\) has parameter \$converted with no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Profile/Shopware6/Converter/NumberRangeConverter.php - - message: "#^Method SwagMigrationAssistant\\\\Profile\\\\Shopware6\\\\Converter\\\\ProductConverter\\:\\:checkDefaultCurrency\\(\\) has parameter \\$source with no value type specified in iterable type array\\.$#" - count: 1 - path: src/Profile/Shopware6/Converter/ProductConverter.php - - - - message: "#^Method SwagMigrationAssistant\\\\Profile\\\\Shopware6\\\\Converter\\\\PropertyGroupConverter\\:\\:convertOption\\(\\) has parameter \\$option with no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Profile\\Shopware6\\Converter\\PropertyGroupConverter\:\:convertOption\(\) has parameter \$option with no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Profile/Shopware6/Converter/PropertyGroupConverter.php - - message: "#^Method SwagMigrationAssistant\\\\Profile\\\\Shopware6\\\\Converter\\\\RuleConverter\\:\\:recursiveAddChildren\\(\\) has parameter \\$parentMap with no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Profile\\Shopware6\\Converter\\RuleConverter\:\:recursiveAddChildren\(\) has parameter \$parentMap with no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Profile/Shopware6/Converter/RuleConverter.php - - message: "#^Method SwagMigrationAssistant\\\\Profile\\\\Shopware6\\\\Converter\\\\RuleConverter\\:\\:recursiveAddChildren\\(\\) has parameter \\$sorted with no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Profile\\Shopware6\\Converter\\RuleConverter\:\:recursiveAddChildren\(\) has parameter \$sorted with no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Profile/Shopware6/Converter/RuleConverter.php - - message: "#^Method SwagMigrationAssistant\\\\Profile\\\\Shopware6\\\\Converter\\\\RuleConverter\\:\\:sortConditions\\(\\) has parameter \\$conditions with no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Profile\\Shopware6\\Converter\\RuleConverter\:\:sortConditions\(\) has parameter \$conditions with no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Profile/Shopware6/Converter/RuleConverter.php - - message: "#^Method SwagMigrationAssistant\\\\Profile\\\\Shopware6\\\\Converter\\\\RuleConverter\\:\\:sortConditions\\(\\) return type has no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Profile\\Shopware6\\Converter\\RuleConverter\:\:sortConditions\(\) return type has no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Profile/Shopware6/Converter/RuleConverter.php - - message: "#^Method SwagMigrationAssistant\\\\Profile\\\\Shopware6\\\\Converter\\\\ShopwareMediaConverter\\:\\:updateMediaAssociation\\(\\) has parameter \\$mediaArray with no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Profile\\Shopware6\\Converter\\ShopwareMediaConverter\:\:updateMediaAssociation\(\) has parameter \$mediaArray with no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Profile/Shopware6/Converter/ShopwareMediaConverter.php - - message: "#^Method SwagMigrationAssistant\\\\Test\\\\DataProvider\\\\Service\\\\EnvironmentServiceTest\\:\\:provideEnvironments\\(\\) return type has no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Test\\DataProvider\\Service\\EnvironmentServiceTest\:\:provideEnvironments\(\) return type has no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: tests/DataProvider/Service/EnvironmentServiceTest.php - - message: "#^Property SwagMigrationAssistant\\\\Test\\\\DeprecatedTagTest\\:\\:\\$whiteList type has no value type specified in iterable type array\\.$#" + message: '#^Property SwagMigrationAssistant\\Test\\DeprecatedTagTest\:\:\$whiteList type has no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: tests/DeprecatedTagTest.php - - message: "#^Method SwagMigrationAssistant\\\\Test\\\\Migration\\\\Converter\\\\ConverterRegistryTest\\:\\:converterProvider\\(\\) return type has no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Test\\Migration\\Converter\\ConverterRegistryTest\:\:converterProvider\(\) return type has no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: tests/Migration/Converter/ConverterRegistryTest.php - - message: "#^Call to deprecated method getMockForAbstractClass\\(\\) of class PHPUnit\\\\Framework\\\\TestCase\\.$#" + message: '#^Call to deprecated method getMockForAbstractClass\(\) of class PHPUnit\\Framework\\TestCase\.$#' + identifier: method.deprecated count: 1 path: tests/Migration/Writer/AbstractWriterTest.php - - message: "#^Property SwagMigrationAssistant\\\\Test\\\\Migration\\\\Writer\\\\AbstractWriterTest\\:\\:\\$dataToWrite type has no value type specified in iterable type array\\.$#" + message: '#^Property SwagMigrationAssistant\\Test\\Migration\\Writer\\AbstractWriterTest\:\:\$dataToWrite type has no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: tests/Migration/Writer/AbstractWriterTest.php - - message: "#^Property SwagMigrationAssistant\\\\Test\\\\Migration\\\\Writer\\\\AbstractWriterTest\\:\\:\\$writeResult type has no value type specified in iterable type array\\.$#" + message: '#^Property SwagMigrationAssistant\\Test\\Migration\\Writer\\AbstractWriterTest\:\:\$writeResult type has no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: tests/Migration/Writer/AbstractWriterTest.php - - message: "#^Class SwagMigrationAssistant\\\\Test\\\\Mock\\\\DummyCollection implements generic interface IteratorAggregate but does not specify its types\\: TKey, TValue$#" + message: '#^Class SwagMigrationAssistant\\Test\\Mock\\DummyCollection implements generic interface IteratorAggregate but does not specify its types\: TKey, TValue$#' + identifier: missingType.generics count: 1 path: tests/Mock/DummyCollection.php - - message: "#^Method SwagMigrationAssistant\\\\Test\\\\Mock\\\\DummyCollection\\:\\:__construct\\(\\) has parameter \\$data with no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Test\\Mock\\DummyCollection\:\:__construct\(\) has parameter \$data with no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: tests/Mock/DummyCollection.php - - message: "#^Method SwagMigrationAssistant\\\\Test\\\\Mock\\\\DummyCollection\\:\\:getIterator\\(\\) return type with generic class ArrayIterator does not specify its types\\: TKey, TValue$#" + message: '#^Method SwagMigrationAssistant\\Test\\Mock\\DummyCollection\:\:getIterator\(\) return type with generic class ArrayIterator does not specify its types\: TKey, TValue$#' + identifier: missingType.generics count: 1 path: tests/Mock/DummyCollection.php - - message: "#^Method SwagMigrationAssistant\\\\Test\\\\Mock\\\\Gateway\\\\Dummy\\\\Api\\\\Reader\\\\ApiDummyReader\\:\\:read\\(\\) return type has no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Test\\Mock\\Gateway\\Dummy\\Api\\Reader\\ApiDummyReader\:\:read\(\) return type has no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: tests/Mock/Gateway/Dummy/Api/Reader/ApiDummyReader.php - - message: "#^Method SwagMigrationAssistant\\\\Test\\\\Mock\\\\Gateway\\\\Dummy\\\\Api\\\\Reader\\\\EnvironmentDummyReader\\:\\:read\\(\\) has parameter \\$params with no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Test\\Mock\\Gateway\\Dummy\\Api\\Reader\\EnvironmentDummyReader\:\:read\(\) has parameter \$params with no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: tests/Mock/Gateway/Dummy/Api/Reader/EnvironmentDummyReader.php - - message: "#^Method SwagMigrationAssistant\\\\Test\\\\Mock\\\\Gateway\\\\Dummy\\\\Api\\\\Reader\\\\TableCountDummyReader\\:\\:readTotals\\(\\) return type has no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Test\\Mock\\Gateway\\Dummy\\Api\\Reader\\TableCountDummyReader\:\:readTotals\(\) return type has no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: tests/Mock/Gateway/Dummy/Api/Reader/TableCountDummyReader.php - - message: "#^Method SwagMigrationAssistant\\\\Test\\\\Mock\\\\Migration\\\\Logging\\\\DummyLoggingService\\:\\:getLoggingArray\\(\\) return type has no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Test\\Mock\\Migration\\Logging\\DummyLoggingService\:\:getLoggingArray\(\) return type has no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: tests/Mock/Migration/Logging/DummyLoggingService.php - - message: "#^Method SwagMigrationAssistant\\\\Test\\\\Mock\\\\Migration\\\\Mapping\\\\Dummy6MappingService\\:\\:createListItemMapping\\(\\) has parameter \\$additionalData with no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Test\\Mock\\Migration\\Mapping\\Dummy6MappingService\:\:createListItemMapping\(\) has parameter \$additionalData with no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: tests/Mock/Migration/Mapping/Dummy6MappingService.php - - message: "#^Method SwagMigrationAssistant\\\\Test\\\\Mock\\\\Migration\\\\Mapping\\\\Dummy6MappingService\\:\\:getMappings\\(\\) has parameter \\$ids with no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Test\\Mock\\Migration\\Mapping\\Dummy6MappingService\:\:getMappings\(\) has parameter \$ids with no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: tests/Mock/Migration/Mapping/Dummy6MappingService.php - - message: "#^Method SwagMigrationAssistant\\\\Test\\\\Mock\\\\Migration\\\\Mapping\\\\Dummy6MappingService\\:\\:getUuidList\\(\\) return type has no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Test\\Mock\\Migration\\Mapping\\Dummy6MappingService\:\:getUuidList\(\) return type has no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: tests/Mock/Migration/Mapping/Dummy6MappingService.php - - message: "#^Method SwagMigrationAssistant\\\\Test\\\\Mock\\\\Migration\\\\Mapping\\\\Dummy6MappingService\\:\\:getUuidsByEntity\\(\\) return type has no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Test\\Mock\\Migration\\Mapping\\Dummy6MappingService\:\:getUuidsByEntity\(\) return type has no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: tests/Mock/Migration/Mapping/Dummy6MappingService.php - - message: "#^Method SwagMigrationAssistant\\\\Test\\\\Mock\\\\Migration\\\\Mapping\\\\Dummy6MappingService\\:\\:preloadMappings\\(\\) has parameter \\$mappingIds with no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Test\\Mock\\Migration\\Mapping\\Dummy6MappingService\:\:preloadMappings\(\) has parameter \$mappingIds with no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: tests/Mock/Migration/Mapping/Dummy6MappingService.php - - message: "#^Method SwagMigrationAssistant\\\\Test\\\\Mock\\\\Migration\\\\Mapping\\\\DummyMappingService\\:\\:createListItemMapping\\(\\) has parameter \\$additionalData with no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Test\\Mock\\Migration\\Mapping\\DummyMappingService\:\:createListItemMapping\(\) has parameter \$additionalData with no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: tests/Mock/Migration/Mapping/DummyMappingService.php - - message: "#^Method SwagMigrationAssistant\\\\Test\\\\Mock\\\\Migration\\\\Mapping\\\\DummyMappingService\\:\\:getMappingArray\\(\\) return type has no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Test\\Mock\\Migration\\Mapping\\DummyMappingService\:\:getMappingArray\(\) return type has no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: tests/Mock/Migration/Mapping/DummyMappingService.php - - message: "#^Method SwagMigrationAssistant\\\\Test\\\\Mock\\\\Migration\\\\Mapping\\\\DummyMappingService\\:\\:getMappings\\(\\) has parameter \\$ids with no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Test\\Mock\\Migration\\Mapping\\DummyMappingService\:\:getMappings\(\) has parameter \$ids with no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: tests/Mock/Migration/Mapping/DummyMappingService.php - - message: "#^Method SwagMigrationAssistant\\\\Test\\\\Mock\\\\Migration\\\\Mapping\\\\DummyMappingService\\:\\:getUuidList\\(\\) return type has no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Test\\Mock\\Migration\\Mapping\\DummyMappingService\:\:getUuidList\(\) return type has no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: tests/Mock/Migration/Mapping/DummyMappingService.php - - message: "#^Method SwagMigrationAssistant\\\\Test\\\\Mock\\\\Migration\\\\Mapping\\\\DummyMappingService\\:\\:getUuidsByEntity\\(\\) return type has no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Test\\Mock\\Migration\\Mapping\\DummyMappingService\:\:getUuidsByEntity\(\) return type has no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: tests/Mock/Migration/Mapping/DummyMappingService.php - - message: "#^Method SwagMigrationAssistant\\\\Test\\\\Mock\\\\Migration\\\\Mapping\\\\DummyMappingService\\:\\:saveMapping\\(\\) has parameter \\$mapping with no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Test\\Mock\\Migration\\Mapping\\DummyMappingService\:\:saveMapping\(\) has parameter \$mapping with no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: tests/Mock/Migration/Mapping/DummyMappingService.php - - message: "#^Method SwagMigrationAssistant\\\\Test\\\\Mock\\\\Migration\\\\Media\\\\DummyMediaFileService\\:\\:getMediaFileArray\\(\\) return type has no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Test\\Mock\\Migration\\Media\\DummyMediaFileService\:\:getMediaFileArray\(\) return type has no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: tests/Mock/Migration/Media/DummyMediaFileService.php - - message: "#^Method SwagMigrationAssistant\\\\Test\\\\Mock\\\\Migration\\\\Media\\\\DummyMediaFileService\\:\\:setWrittenFlag\\(\\) has parameter \\$converted with no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Test\\Mock\\Migration\\Media\\DummyMediaFileService\:\:setWrittenFlag\(\) has parameter \$converted with no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: tests/Mock/Migration/Media/DummyMediaFileService.php - - message: "#^Method SwagMigrationAssistant\\\\Test\\\\Mock\\\\Migration\\\\Writer\\\\DummyWriter\\:\\:writeData\\(\\) has parameter \\$data with no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Test\\Mock\\Migration\\Writer\\DummyWriter\:\:writeData\(\) has parameter \$data with no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: tests/Mock/Migration/Writer/DummyWriter.php - - message: "#^Method SwagMigrationAssistant\\\\Test\\\\Mock\\\\Migration\\\\Writer\\\\DummyWriter\\:\\:writeData\\(\\) return type has no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Test\\Mock\\Migration\\Writer\\DummyWriter\:\:writeData\(\) return type has no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: tests/Mock/Migration/Writer/DummyWriter.php - - message: "#^Parameter \\#3 \\$body of class GuzzleHttp\\\\Psr7\\\\Response constructor expects Psr\\\\Http\\\\Message\\\\StreamInterface\\|resource\\|string\\|null, string\\|false given\\.$#" + message: '#^Parameter \#3 \$body of class GuzzleHttp\\Psr7\\Response constructor expects Psr\\Http\\Message\\StreamInterface\|resource\|string\|null, string\|false given\.$#' + identifier: argument.type count: 1 path: tests/Profile/Shopware/Gateway/ApiReaderTest.php - - message: "#^Method SwagMigrationAssistant\\\\Test\\\\Profile\\\\Shopware\\\\Gateway\\\\LocalGatewayTest\\:\\:profileProvider\\(\\) return type has no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Test\\Profile\\Shopware\\Gateway\\LocalGatewayTest\:\:profileProvider\(\) return type has no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: tests/Profile/Shopware/Gateway/LocalGatewayTest.php - - message: "#^Method SwagMigrationAssistant\\\\Test\\\\Profile\\\\Shopware6\\\\Converter\\\\ProductSortingConverterTest\\:\\:loadMapping\\(\\) has parameter \\$mappingArray with no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Test\\Profile\\Shopware6\\Converter\\ProductSortingConverterTest\:\:loadMapping\(\) has parameter \$mappingArray with no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: tests/Profile/Shopware6/Converter/ProductSortingConverterTest.php - - message: "#^Method SwagMigrationAssistant\\\\Test\\\\Profile\\\\Shopware6\\\\Converter\\\\ShopwareConverterTest\\:\\:dataProviderConvert\\(\\) return type has no value type specified in iterable type iterable\\.$#" + message: '#^Method SwagMigrationAssistant\\Test\\Profile\\Shopware6\\Converter\\ShopwareConverterTest\:\:dataProviderConvert\(\) return type has no value type specified in iterable type iterable\.$#' + identifier: missingType.iterableValue count: 1 path: tests/Profile/Shopware6/Converter/ShopwareConverterTest.php - - message: "#^Method SwagMigrationAssistant\\\\Test\\\\Profile\\\\Shopware6\\\\Converter\\\\ShopwareConverterTest\\:\\:loadMapping\\(\\) has parameter \\$mappingArray with no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Test\\Profile\\Shopware6\\Converter\\ShopwareConverterTest\:\:loadMapping\(\) has parameter \$mappingArray with no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: tests/Profile/Shopware6/Converter/ShopwareConverterTest.php - - message: "#^Method SwagMigrationAssistant\\\\Test\\\\Profile\\\\Shopware6\\\\Gateway\\\\Connection\\\\ConnectionFactoryTests\\:\\:testCreateApiClient\\(\\) has parameter \\$credentials with no value type specified in iterable type array\\.$#" + message: '#^Method SwagMigrationAssistant\\Test\\Profile\\Shopware6\\Gateway\\Connection\\ConnectionFactoryTests\:\:testCreateApiClient\(\) has parameter \$credentials with no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: tests/Profile/Shopware6/Gateway/Connection/ConnectionFactoryTests.php diff --git a/phpstan.neon.dist b/phpstan.neon.dist index 6eba93c02..f236d3685 100644 --- a/phpstan.neon.dist +++ b/phpstan.neon.dist @@ -18,27 +18,13 @@ parameters: consoleApplicationLoader: %ShopwareRoot%/src/Core/DevOps/StaticAnalyze/console-application.php type_perfect: narrow_return: true - narrow_param: true + narrow_param: false ignoreErrors: - message: '#Service ".*" is private#' paths: - tests/**/*Test.php - - # Ignore hash functions rule for the following files because we use it in another context - message: '#Do not use .* function, use class Shopware\\Core\\Framework\\Util\\Hasher instead#' - paths: - - src/Migration/Media/Processor/HttpDownloadServiceBase.php - - src/Migration/Service/MigrationDataConverter.php - - src/Profile/Shopware/Converter/OrderConverter.php - - src/Profile/Shopware/Converter/ProductConverter.php - - src/Profile/Shopware/Converter/ProductOptionRelationConverter.php - - src/Profile/Shopware/Converter/ProductPropertyRelationConverter.php - - src/Profile/Shopware/Converter/PropertyGroupOptionConverter.php - - src/Profile/Shopware/Converter/ShippingMethodConverter.php - - src/Profile/Shopware/Media/Strategy/Md5StrategyResolver.php - - src/Migration/Converter/Converter.php - - # To fix those issues, the AbstractProvider needs a generic type, which could then be used further down in the methods as typehints for other generic typed parameters message: '#(readTotalFromRepo|readTableFromRepo|cleanupSearchResult)\(\) has parameter .* with generic class#' path: src/DataProvider/Provider/Data/AbstractProvider.php diff --git a/src/Command/AbortMigrationCommand.php b/src/Command/AbortMigrationCommand.php deleted file mode 100644 index 6b4619b0a..000000000 --- a/src/Command/AbortMigrationCommand.php +++ /dev/null @@ -1,49 +0,0 @@ - - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace SwagMigrationAssistant\Command; - -use Shopware\Core\Framework\Context; -use Shopware\Core\Framework\Log\Package; -use SwagMigrationAssistant\Exception\NoRunningMigrationException; -use SwagMigrationAssistant\Migration\Run\RunServiceInterface; -use Symfony\Component\Console\Attribute\AsCommand; -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Output\OutputInterface; - -#[Package('fundamentals@after-sales')] -#[AsCommand( - name: 'migration:abort', - description: 'Abort the current migration', -)] -class AbortMigrationCommand extends Command -{ - public function __construct( - private readonly RunServiceInterface $runService, - ?string $name = null, - ) { - parent::__construct($name); - } - - protected function execute(InputInterface $input, OutputInterface $output): int - { - $context = Context::createCLIContext(); - - try { - $this->runService->abortMigration($context); - } catch (NoRunningMigrationException $exception) { - $output->writeln('Currently there is no migration running.'); - - return Command::FAILURE; - } - - $output->writeln('The migration is aborted.'); - - return Command::SUCCESS; - } -} diff --git a/src/Command/GetMigrationProgressCommand.php b/src/Command/GetMigrationProgressCommand.php deleted file mode 100644 index 22d0a8ce5..000000000 --- a/src/Command/GetMigrationProgressCommand.php +++ /dev/null @@ -1,91 +0,0 @@ - - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace SwagMigrationAssistant\Command; - -use Shopware\Core\Framework\Context; -use Shopware\Core\Framework\Log\Package; -use SwagMigrationAssistant\Migration\Run\MigrationStep; -use SwagMigrationAssistant\Migration\Run\RunServiceInterface; -use Symfony\Component\Console\Attribute\AsCommand; -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Helper\ProgressBar; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Input\InputOption; -use Symfony\Component\Console\Output\OutputInterface; - -#[Package('fundamentals@after-sales')] -#[AsCommand( - name: 'migration:get-progress', - description: 'Shows the current progress of a migration', -)] -class GetMigrationProgressCommand extends Command -{ - private const PROGRESSBAR_FORMAT = '[%bar%] %current%/%max% '; - - public function __construct( - private readonly RunServiceInterface $runService, - ?string $name = null, - ) { - parent::__construct($name); - } - - protected function configure(): void - { - $this->addOption('refreshRate', 'r', InputOption::VALUE_OPTIONAL, 'Refresh rate in milliseconds', 500); - } - - protected function execute(InputInterface $input, OutputInterface $output): int - { - $context = Context::createCLIContext(); - $refreshRateMs = (int) $input->getOption('refreshRate'); - if ($refreshRateMs < 250) { - $refreshRateMs = 250; - $output->writeln('refreshRates smaller than 250ms are not supported, falling back to 250ms.'); - } - - $migrationState = $this->runService->getRunStatus($context); - - if ($migrationState->getStep() === MigrationStep::IDLE) { - $output->writeln('Currently there is no migration running'); - - return Command::FAILURE; - } - - $progressBar = new ProgressBar($output, $migrationState->getTotal()); - $progressBar->setFormat(self::PROGRESSBAR_FORMAT . $migrationState->getStepValue()); - $progressBar->setMaxSteps($migrationState->getTotal()); - $progressBar->setProgress($migrationState->getProgress()); - - while ($migrationState->getStep() !== MigrationStep::FINISHED) { - $migrationState = $this->runService->getRunStatus($context); - - if ($migrationState->getStep() === MigrationStep::IDLE) { - $output->writeln(''); - $output->writeln('Migration was aborted.'); - - break; - } - - if ($migrationState->getStep() === MigrationStep::WAITING_FOR_APPROVE) { - $this->runService->approveFinishingMigration($context); - $output->writeln(''); - $output->writeln('Migration is finished.'); - - break; - } - - $progressBar->setFormat(self::PROGRESSBAR_FORMAT . $migrationState->getStepValue()); - $progressBar->setMaxSteps($migrationState->getTotal()); - $progressBar->setProgress($migrationState->getProgress()); - - \usleep($refreshRateMs * 1000); - } - - return Command::SUCCESS; - } -} diff --git a/src/Command/StartMigrationCommand.php b/src/Command/StartMigrationCommand.php deleted file mode 100644 index 79be7fb01..000000000 --- a/src/Command/StartMigrationCommand.php +++ /dev/null @@ -1,88 +0,0 @@ - - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace SwagMigrationAssistant\Command; - -use Shopware\Core\Framework\Context; -use Shopware\Core\Framework\Log\Package; -use SwagMigrationAssistant\Exception\MigrationIsAlreadyRunningException; -use SwagMigrationAssistant\Exception\PremappingIsIncompleteException; -use SwagMigrationAssistant\Migration\Run\RunServiceInterface; -use SwagMigrationAssistant\Profile\Shopware\DataSelection\BasicSettingsDataSelection; -use Symfony\Component\Console\Attribute\AsCommand; -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Input\InputArgument; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Output\OutputInterface; - -#[Package('fundamentals@after-sales')] -#[AsCommand( - name: 'migration:start', - description: 'Migrate the data of your selected source to Shopware 6. Before you execute this command - you have to configure the migration in the Shopware 6 administration.', -)] -class StartMigrationCommand extends Command -{ - /** - * @var string[] - */ - private array $dataSelectionNames = []; - - public function __construct( - private readonly RunServiceInterface $runService, - ?string $name = null, - ) { - parent::__construct($name); - } - - protected function configure(): void - { - $this->addArgument('dataSelections', InputArgument::IS_ARRAY | InputArgument::REQUIRED); - } - - protected function execute(InputInterface $input, OutputInterface $output): int - { - $context = Context::createCLIContext(); - - if (!$this->validateDataSelections($input)) { - $output->writeln('Please provide at least one data selection.'); - - return Command::FAILURE; - } - - try { - $this->runService->startMigrationRun($this->dataSelectionNames, $context); - } catch (MigrationIsAlreadyRunningException $exception) { - $output->writeln('Migration is already running, please use `migration:get-progress` to check the progress.'); - - return Command::FAILURE; - } catch (PremappingIsIncompleteException $exception) { - $output->writeln('Premapping is incomplete, please fill it in before performing the migration.'); - - return Command::FAILURE; - } - - $output->writeln('Migration is started, please use migration:get-progress to check the progress.'); - - return Command::SUCCESS; - } - - private function validateDataSelections(InputInterface $input): bool - { - $dataSelections = $input->getArgument('dataSelections'); - if (!$dataSelections) { - return false; - } - if (!\is_array($dataSelections)) { - $dataSelections = [$dataSelections]; - } - $this->dataSelectionNames[] = BasicSettingsDataSelection::IDENTIFIER; - $this->dataSelectionNames = \array_merge($this->dataSelectionNames, $dataSelections); - - return true; - } -} diff --git a/src/Controller/DataProviderController.php b/src/Controller/DataProviderController.php index 7d4573493..29f1c56f4 100644 --- a/src/Controller/DataProviderController.php +++ b/src/Controller/DataProviderController.php @@ -23,6 +23,7 @@ use SwagMigrationAssistant\DataProvider\Provider\ProviderRegistryInterface; use SwagMigrationAssistant\DataProvider\Service\EnvironmentServiceInterface; use SwagMigrationAssistant\Exception\MigrationException; +use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\HeaderUtils; use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\HttpFoundation\RedirectResponse; @@ -33,9 +34,11 @@ #[Route(defaults: ['_routeScope' => ['api']])] #[Package('fundamentals@after-sales')] -final class DataProviderController +class DataProviderController extends AbstractController { /** + * @internal + * * @param EntityRepository $mediaRepository */ public function __construct( diff --git a/src/Controller/HistoryController.php b/src/Controller/HistoryController.php index 20800612f..16ac27c42 100644 --- a/src/Controller/HistoryController.php +++ b/src/Controller/HistoryController.php @@ -12,6 +12,7 @@ use Shopware\Core\Framework\Routing\RoutingException; use SwagMigrationAssistant\Exception\MigrationException; use SwagMigrationAssistant\Migration\History\HistoryServiceInterface; +use SwagMigrationAssistant\Migration\History\LogGroupingService; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\HeaderUtils; use Symfony\Component\HttpFoundation\JsonResponse; @@ -25,11 +26,16 @@ #[Package('fundamentals@after-sales')] class HistoryController extends AbstractController { - public function __construct(private readonly HistoryServiceInterface $historyService) - { + /** + * @internal + */ + public function __construct( + private readonly HistoryServiceInterface $historyService, + private readonly LogGroupingService $logGroupingService, + ) { } - #[Route(path: '/api/migration/get-grouped-logs-of-run', name: 'api.admin.migration.get-grouped-logs-of-run', methods: ['GET'], defaults: ['_acl' => ['admin']])] + #[Route(path: '/api/_action/migration/get-grouped-logs-of-run', name: 'api.admin.migration.get-grouped-logs-of-run', methods: ['GET'], defaults: ['_acl' => ['swag_migration.viewer']])] public function getGroupedLogsOfRun(Request $request, Context $context): JsonResponse { $runUuid = $request->query->getAlnum('runUuid'); @@ -54,7 +60,7 @@ public function getGroupedLogsOfRun(Request $request, Context $context): JsonRes ]); } - #[Route(path: '/api/_action/migration/download-logs-of-run', name: 'api.admin.migration.download-logs-of-run', methods: ['POST'], defaults: ['auth_required' => false, '_acl' => ['admin']])] + #[Route(path: '/api/_action/migration/download-logs-of-run', name: 'api.admin.migration.download-logs-of-run', methods: ['POST'], defaults: ['auth_required' => false, '_acl' => ['swag_migration.viewer']])] public function downloadLogsOfRun(Request $request, Context $context): StreamedResponse { $runUuid = $request->request->getAlnum('runUuid'); @@ -80,7 +86,7 @@ public function downloadLogsOfRun(Request $request, Context $context): StreamedR return $response; } - #[Route(path: '/api/_action/migration/clear-data-of-run', name: 'api.admin.migration.clear-data-of-run', methods: ['POST'], defaults: ['_acl' => ['admin']])] + #[Route(path: '/api/_action/migration/clear-data-of-run', name: 'api.admin.migration.clear-data-of-run', methods: ['POST'], defaults: ['_acl' => ['swag_migration.deleter']])] public function clearDataOfRun(Request $request, Context $context): Response { $runUuid = $request->request->getAlnum('runUuid'); @@ -90,7 +96,7 @@ public function clearDataOfRun(Request $request, Context $context): Response } if ($this->historyService->isMediaProcessing()) { - throw MigrationException::migrationIsAlreadyRunning(); + throw MigrationException::migrationProcessing(); } $this->historyService->clearDataOfRun($runUuid, $context); @@ -98,11 +104,109 @@ public function clearDataOfRun(Request $request, Context $context): Response return new Response(); } - #[Route(path: '/api/_action/migration/is-media-processing', name: 'api.admin.migration.is-media-processing', methods: ['GET'], defaults: ['_acl' => ['admin']])] + #[Route(path: '/api/_action/migration/is-media-processing', name: 'api.admin.migration.is-media-processing', methods: ['GET'], defaults: ['_acl' => ['swag_migration_history:read']])] public function isMediaProcessing(): JsonResponse { $result = $this->historyService->isMediaProcessing(); return new JsonResponse($result); } + + #[Route( + path: '/api/_action/migration/get-log-groups', + name: 'api.admin.migration.get-log-groups', + methods: ['GET'], + defaults: ['_acl' => ['swag_migration.viewer']] + )] + public function getLogGroups(Request $request, Context $context): JsonResponse + { + $runId = $request->query->getAlnum('runId'); + + if (empty($runId)) { + throw RoutingException::missingRequestParameter('runId'); + } + + $level = $request->query->getAlpha('level'); + + if (empty($level)) { + throw RoutingException::missingRequestParameter('level'); + } + + $page = $request->query->getInt('page', 1); + $limit = $request->query->getInt('limit', 25); + + $sortBy = $request->query->getAlpha('sortBy') ?: 'count'; + $sortDirection = $request->query->getAlpha('sortDirection') ?: 'DESC'; + + if (!\in_array(\strtoupper($sortDirection), ['ASC', 'DESC'], true)) { + $sortDirection = 'DESC'; + } + + $filterCode = $request->query->get('filterCode'); + $filterStatus = $request->query->get('filterStatus'); + $filterEntity = $request->query->get('filterEntity'); + $filterField = $request->query->get('filterField'); + + $result = $this->logGroupingService->getGroupedLogsByCodeAndEntity( + $runId, + $level, + $page, + $limit, + $sortBy, + \strtoupper($sortDirection), + \is_string($filterCode) && !empty($filterCode) ? $filterCode : null, + \is_string($filterStatus) && !empty($filterStatus) ? $filterStatus : null, + \is_string($filterEntity) && !empty($filterEntity) ? $filterEntity : null, + \is_string($filterField) && !empty($filterField) ? $filterField : null, + ); + + return new JsonResponse($result); + } + + #[Route( + path: '/api/_action/migration/get-all-log-ids', + name: 'api.admin.migration.get-all-log-ids', + methods: ['POST'], + defaults: ['_acl' => ['swag_migration.viewer']] + )] + public function getAllLogIds(Request $request): JsonResponse + { + $runId = $request->request->getAlnum('runId'); + + if (empty($runId)) { + throw RoutingException::missingRequestParameter('runId'); + } + + $code = $request->request->get('code'); + + if (!\is_string($code) || empty($code)) { + throw RoutingException::missingRequestParameter('code'); + } + + $entityName = $request->request->get('entityName'); + + if (!\is_string($entityName) || empty($entityName)) { + throw RoutingException::missingRequestParameter('entityName'); + } + + $fieldName = $request->request->get('fieldName'); + + if (!\is_string($fieldName) || empty($fieldName)) { + throw RoutingException::missingRequestParameter('fieldName'); + } + + $connectionId = $request->request->getAlnum('connectionId'); + + $logIds = $this->logGroupingService->getAllLogIdsByCodeAndEntity( + $runId, + $code, + $entityName, + $fieldName, + !empty($connectionId) ? $connectionId : null + ); + + return new JsonResponse([ + 'ids' => $logIds, + ]); + } } diff --git a/src/Controller/PremappingController.php b/src/Controller/PremappingController.php index 87f33621a..078990a1d 100644 --- a/src/Controller/PremappingController.php +++ b/src/Controller/PremappingController.php @@ -22,13 +22,16 @@ #[Package('fundamentals@after-sales')] class PremappingController extends AbstractController { + /** + * @internal + */ public function __construct( private readonly PremappingServiceInterface $premappingService, private readonly MigrationContextFactoryInterface $migrationContextFactory, ) { } - #[Route(path: '/api/_action/migration/generate-premapping', name: 'api.admin.migration.generate-premapping', methods: ['POST'], defaults: ['_acl' => ['admin']])] + #[Route(path: '/api/_action/migration/generate-premapping', name: 'api.admin.migration.generate-premapping', methods: ['POST'], defaults: ['_acl' => ['swag_migration.editor']])] public function generatePremapping(Request $request, Context $context): JsonResponse { $dataSelectionIds = $request->request->all('dataSelectionIds'); @@ -41,7 +44,7 @@ public function generatePremapping(Request $request, Context $context): JsonResp return new JsonResponse($this->premappingService->generatePremapping($context, $migrationContext, $dataSelectionIds)); } - #[Route(path: '/api/_action/migration/write-premapping', name: 'api.admin.migration.write-premapping', methods: ['POST'], defaults: ['_acl' => ['admin']])] + #[Route(path: '/api/_action/migration/write-premapping', name: 'api.admin.migration.write-premapping', methods: ['POST'], defaults: ['_acl' => ['swag_migration.editor']])] public function writePremapping(Request $request, Context $context): Response { $premapping = $request->request->all('premapping'); diff --git a/src/Controller/StatusController.php b/src/Controller/StatusController.php index 65af65ab1..5f6395be0 100644 --- a/src/Controller/StatusController.php +++ b/src/Controller/StatusController.php @@ -13,9 +13,12 @@ use Shopware\Core\Framework\Log\Package; use Shopware\Core\Framework\Routing\RoutingException; use SwagMigrationAssistant\Exception\MigrationException; +use SwagMigrationAssistant\Migration\Connection\Fingerprint\MigrationFingerprintServiceInterface; use SwagMigrationAssistant\Migration\Connection\SwagMigrationConnectionCollection; +use SwagMigrationAssistant\Migration\Connection\SwagMigrationConnectionEntity; use SwagMigrationAssistant\Migration\DataSelection\DataSelectionRegistryInterface; use SwagMigrationAssistant\Migration\Gateway\GatewayRegistryInterface; +use SwagMigrationAssistant\Migration\MigrationContext; use SwagMigrationAssistant\Migration\MigrationContextFactoryInterface; use SwagMigrationAssistant\Migration\Profile\ProfileRegistryInterface; use SwagMigrationAssistant\Migration\Run\RunServiceInterface; @@ -32,6 +35,8 @@ class StatusController extends AbstractController { /** + * @internal + * * @param EntityRepository $migrationConnectionRepo * @param EntityRepository $generalSettingRepo */ @@ -44,13 +49,14 @@ public function __construct( private readonly GatewayRegistryInterface $gatewayRegistry, private readonly MigrationContextFactoryInterface $migrationContextFactory, private readonly EntityRepository $generalSettingRepo, + private readonly MigrationFingerprintServiceInterface $fingerprintService, ) { } #[Route( path: '/api/_action/migration/get-profile-information', name: 'api.admin.migration.get-profile-information', - defaults: ['_acl' => ['admin']], + defaults: ['_acl' => ['swag_migration.viewer']], methods: [Request::METHOD_GET] )] public function getProfileInformation(Request $request): Response @@ -87,8 +93,11 @@ public function getProfileInformation(Request $request): Response return new Response(); } - $migrationContext = $this->migrationContextFactory->createByProfileName($profileName); - $gateways = $this->gatewayRegistry->getGateways($migrationContext); + $profile = $this->profileRegistry->getProfile($profileName); + $context = new MigrationContext(new SwagMigrationConnectionEntity()); + $context->setProfile($profile); + + $gateways = $this->gatewayRegistry->getGateways($context); $currentGateway = null; foreach ($gateways as $gateway) { @@ -117,7 +126,7 @@ public function getProfileInformation(Request $request): Response #[Route( path: '/api/_action/migration/get-profiles', name: 'api.admin.migration.get-profiles', - defaults: ['_acl' => ['admin']], + defaults: ['_acl' => ['swag_migration.viewer']], methods: [Request::METHOD_GET] )] public function getProfiles(): JsonResponse @@ -140,7 +149,7 @@ public function getProfiles(): JsonResponse #[Route( path: '/api/_action/migration/get-gateways', name: 'api.admin.migration.get-gateways', - defaults: ['_acl' => ['admin']], + defaults: ['_acl' => ['swag_migration.viewer']], methods: [Request::METHOD_GET] )] public function getGateways(Request $request): JsonResponse @@ -151,8 +160,11 @@ public function getGateways(Request $request): JsonResponse throw RoutingException::missingRequestParameter('profileName'); } - $migrationContext = $this->migrationContextFactory->createByProfileName($profileName); - $gateways = $this->gatewayRegistry->getGateways($migrationContext); + $profile = $this->profileRegistry->getProfile($profileName); + $context = new MigrationContext(new SwagMigrationConnectionEntity()); + $context->setProfile($profile); + + $gateways = $this->gatewayRegistry->getGateways($context); $gatewayNames = []; foreach ($gateways as $gateway) { @@ -168,7 +180,7 @@ public function getGateways(Request $request): JsonResponse #[Route( path: '/api/_action/migration/update-connection-credentials', name: 'api.admin.migration.update-connection-credentials', - defaults: ['_acl' => ['admin']], + defaults: ['_acl' => ['swag_migration.editor']], methods: [Request::METHOD_POST] )] public function updateConnectionCredentials(Request $request, Context $context): Response @@ -195,7 +207,7 @@ public function updateConnectionCredentials(Request $request, Context $context): #[Route( path: '/api/_action/migration/data-selection', name: 'api.admin.migration.data-selection', - defaults: ['_acl' => ['admin']], + defaults: ['_acl' => ['swag_migration.viewer']], methods: [Request::METHOD_GET] )] public function getDataSelection(Request $request, Context $context): JsonResponse @@ -222,7 +234,7 @@ public function getDataSelection(Request $request, Context $context): JsonRespon #[Route( path: '/api/_action/migration/check-connection', name: 'api.admin.migration.check-connection', - defaults: ['_acl' => ['admin']], + defaults: ['_acl' => ['swag_migration.viewer']], methods: [Request::METHOD_POST] )] public function checkConnection(Request $request, Context $context): JsonResponse @@ -239,16 +251,43 @@ public function checkConnection(Request $request, Context $context): JsonRespons throw MigrationException::noConnectionFound(); } + $credentialFields = $request->request->all('credentialFields'); + + if (!empty($credentialFields)) { + $connection->setCredentialFields($credentialFields); + } + $migrationContext = $this->migrationContextFactory->createByConnection($connection); $information = $this->migrationDataFetcher->getEnvironmentInformation($migrationContext, $context); + if ($information->getFingerprint() === null) { + return new JsonResponse($information); + } + + $hasDuplicate = $this->fingerprintService->searchDuplicates( + $information->getFingerprint(), + $context, + $connectionId + ); + + if ($hasDuplicate) { + throw MigrationException::duplicateSourceConnection(); + } + + $this->migrationConnectionRepo->update([ + [ + 'id' => $connectionId, + 'sourceSystemFingerprint' => $information->getFingerprint(), + ], + ], $context); + return new JsonResponse($information); } #[Route( path: '/api/_action/migration/start-migration', name: 'api.admin.migration.start-migration', - defaults: ['_acl' => ['admin']], + defaults: ['_acl' => ['swag_migration.creator']], methods: [Request::METHOD_POST] )] public function startMigration(Request $request, Context $context): Response @@ -281,7 +320,7 @@ public function startMigration(Request $request, Context $context): Response #[Route( path: '/api/_action/migration/get-state', name: 'api.admin.migration.get-state', - defaults: ['_acl' => ['admin']], + defaults: ['_acl' => ['swag_migration.viewer']], methods: [Request::METHOD_GET] )] public function getState(Context $context): JsonResponse @@ -292,7 +331,7 @@ public function getState(Context $context): JsonResponse #[Route( path: '/api/_action/migration/approve-finished', name: 'api.admin.migration.approveFinished', - defaults: ['_acl' => ['admin']], + defaults: ['_acl' => ['swag_migration.editor']], methods: [Request::METHOD_POST] )] public function approveFinishedMigration(Context $context): Response @@ -313,16 +352,12 @@ public function approveFinishedMigration(Context $context): Response #[Route( path: '/api/_action/migration/abort-migration', name: 'api.admin.migration.abort-migration', - defaults: ['_acl' => ['admin']], + defaults: ['_acl' => ['swag_migration.editor']], methods: [Request::METHOD_POST] )] public function abortMigration(Context $context): Response { - try { - $this->runService->abortMigration($context); - } catch (\Exception $e) { - return new Response($e->getMessage(), Response::HTTP_BAD_REQUEST); - } + $this->runService->abortMigration($context); return new Response(null, Response::HTTP_NO_CONTENT); } @@ -330,7 +365,7 @@ public function abortMigration(Context $context): Response #[Route( path: '/api/_action/migration/reset-checksums', name: 'api.admin.migration.reset-checksums', - defaults: ['_acl' => ['admin']], + defaults: ['_acl' => ['swag_migration.deleter']], methods: [Request::METHOD_POST] )] public function resetChecksums(Request $request, Context $context): Response @@ -341,14 +376,7 @@ public function resetChecksums(Request $request, Context $context): Response throw RoutingException::missingRequestParameter('connectionId'); } - $connection = $this->migrationConnectionRepo->search(new Criteria([$connectionId]), $context)->getEntities()->first(); - - if ($connection === null) { - throw MigrationException::noConnectionFound(); - } - - // ToDo: MIG-965 - Check how we could put this into the MQ - $this->runService->cleanupMappingChecksums($connectionId, $context); + $this->runService->startCleanupMappingChecksums($connectionId, $context); return new Response(); } @@ -356,23 +384,23 @@ public function resetChecksums(Request $request, Context $context): Response #[Route( path: '/api/_action/migration/cleanup-migration-data', name: 'api.admin.migration.cleanup-migration-data', - defaults: ['_acl' => ['admin']], + defaults: ['_acl' => ['swag_migration.deleter']], methods: [Request::METHOD_POST] )] public function cleanupMigrationData(Context $context): Response { - $this->runService->cleanupMigrationData($context); + $this->runService->startTruncateMigrationData($context); return new Response(); } #[Route( - path: '/api/_action/migration/get-reset-status', + path: '/api/_action/migration/is-truncating-migration-data', name: 'api.admin.migration.get-reset-status', - defaults: ['_acl' => ['admin']], + defaults: ['_acl' => ['swag_migration.viewer']], methods: [Request::METHOD_GET] )] - public function getResetStatus(Context $context): JsonResponse + public function isTruncatingMigrationData(Context $context): JsonResponse { $settings = $this->generalSettingRepo->search(new Criteria(), $context)->getEntities()->first(); @@ -382,4 +410,39 @@ public function getResetStatus(Context $context): JsonResponse return new JsonResponse($settings->isReset()); } + + #[Route( + path: '/api/_action/migration/is-resetting-checksums', + name: 'api.admin.migration.is-resetting-checksums', + defaults: ['_acl' => ['swag_migration.viewer']], + methods: [Request::METHOD_GET] + )] + public function isResettingChecksums(Context $context): JsonResponse + { + $settings = $this->generalSettingRepo + ->search(new Criteria(), $context) + ->getEntities() + ->first(); + + if ($settings === null) { + return new JsonResponse(false); + } + + return new JsonResponse( + $settings->isResettingChecksums() + ); + } + + #[Route( + path: '/api/_action/migration/resume-after-fixes', + name: 'api.admin.migration.resume-after-fixes', + defaults: ['_acl' => ['admin']], + methods: [Request::METHOD_POST] + )] + public function resumeAfterFixes(Context $context): Response + { + $this->runService->resumeAfterFixes($context); + + return new Response(null, Response::HTTP_NO_CONTENT); + } } diff --git a/src/Core/Field/AnyJsonField.php b/src/Core/Field/AnyJsonField.php new file mode 100644 index 000000000..a6c8de7bd --- /dev/null +++ b/src/Core/Field/AnyJsonField.php @@ -0,0 +1,41 @@ + + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace SwagMigrationAssistant\Core\Field; + +use Shopware\Core\Framework\DataAbstractionLayer\Field\Field; +use Shopware\Core\Framework\DataAbstractionLayer\Field\StorageAware; +use Shopware\Core\Framework\Log\Package; + +/** + * This is an alternative for the JsonField and allows to save all simple data types + * into a JSON database field, not just arrays. + * + * int, float, string, null and array + * + * @internal + */ +#[Package('fundamentals@after-sales')] +class AnyJsonField extends Field implements StorageAware +{ + public function __construct( + private readonly string $storageName, + string $propertyName, + ) { + parent::__construct($propertyName); + } + + public function getStorageName(): string + { + return $this->storageName; + } + + protected function getSerializerClass(): string + { + return AnyJsonFieldSerializer::class; + } +} diff --git a/src/Core/Field/AnyJsonFieldSerializer.php b/src/Core/Field/AnyJsonFieldSerializer.php new file mode 100644 index 000000000..88e9b2096 --- /dev/null +++ b/src/Core/Field/AnyJsonFieldSerializer.php @@ -0,0 +1,46 @@ + + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace SwagMigrationAssistant\Core\Field; + +use Shopware\Core\Framework\DataAbstractionLayer\DataAbstractionLayerException; +use Shopware\Core\Framework\DataAbstractionLayer\Field\Field; +use Shopware\Core\Framework\DataAbstractionLayer\FieldSerializer\AbstractFieldSerializer; +use Shopware\Core\Framework\DataAbstractionLayer\Write\DataStack\KeyValuePair; +use Shopware\Core\Framework\DataAbstractionLayer\Write\EntityExistence; +use Shopware\Core\Framework\DataAbstractionLayer\Write\WriteParameterBag; +use Shopware\Core\Framework\Log\Package; +use Shopware\Core\Framework\Util\Json; + +/** + * @internal + */ +#[Package('fundamentals@after-sales')] +class AnyJsonFieldSerializer extends AbstractFieldSerializer +{ + public function encode(Field $field, EntityExistence $existence, KeyValuePair $data, WriteParameterBag $parameters): \Generator + { + if (!$field instanceof AnyJsonField) { + throw DataAbstractionLayerException::invalidSerializerField(AnyJsonField::class, $field); + } + + $value = $data->getValue(); + + $value = Json::encode($value); + + yield $field->getStorageName() => $value; + } + + public function decode(Field $field, mixed $value): mixed + { + if (!$field instanceof AnyJsonField) { + throw DataAbstractionLayerException::invalidSerializerField(AnyJsonField::class, $field); + } + + return json_decode($value, true, 512, \JSON_THROW_ON_ERROR); + } +} diff --git a/src/Core/Migration/Migration1536765935Connection.php b/src/Core/Migration/Migration1536765935Connection.php index 0c1d79815..ab799a64b 100644 --- a/src/Core/Migration/Migration1536765935Connection.php +++ b/src/Core/Migration/Migration1536765935Connection.php @@ -11,6 +11,9 @@ use Shopware\Core\Framework\Log\Package; use Shopware\Core\Framework\Migration\MigrationStep; +/** + * @internal + */ #[Package('fundamentals@after-sales')] class Migration1536765935Connection extends MigrationStep { diff --git a/src/Core/Migration/Migration1536765936Run.php b/src/Core/Migration/Migration1536765936Run.php index 7fee4e465..f18c2232a 100644 --- a/src/Core/Migration/Migration1536765936Run.php +++ b/src/Core/Migration/Migration1536765936Run.php @@ -11,6 +11,9 @@ use Shopware\Core\Framework\Log\Package; use Shopware\Core\Framework\Migration\MigrationStep; +/** + * @internal + */ #[Package('fundamentals@after-sales')] class Migration1536765936Run extends MigrationStep { diff --git a/src/Core/Migration/Migration1536765937Data.php b/src/Core/Migration/Migration1536765937Data.php index ce163ab84..2e99fbf35 100644 --- a/src/Core/Migration/Migration1536765937Data.php +++ b/src/Core/Migration/Migration1536765937Data.php @@ -11,6 +11,9 @@ use Shopware\Core\Framework\Log\Package; use Shopware\Core\Framework\Migration\MigrationStep; +/** + * @internal + */ #[Package('fundamentals@after-sales')] class Migration1536765937Data extends MigrationStep { diff --git a/src/Core/Migration/Migration1536765938Mapping.php b/src/Core/Migration/Migration1536765938Mapping.php index bf2b091a0..1e5529454 100644 --- a/src/Core/Migration/Migration1536765938Mapping.php +++ b/src/Core/Migration/Migration1536765938Mapping.php @@ -11,6 +11,9 @@ use Shopware\Core\Framework\Log\Package; use Shopware\Core\Framework\Migration\MigrationStep; +/** + * @internal + */ #[Package('fundamentals@after-sales')] class Migration1536765938Mapping extends MigrationStep { diff --git a/src/Core/Migration/Migration1538046469MediaFile.php b/src/Core/Migration/Migration1538046469MediaFile.php index 8e22fa8d4..aa27b2f6b 100644 --- a/src/Core/Migration/Migration1538046469MediaFile.php +++ b/src/Core/Migration/Migration1538046469MediaFile.php @@ -11,6 +11,9 @@ use Shopware\Core\Framework\Log\Package; use Shopware\Core\Framework\Migration\MigrationStep; +/** + * @internal + */ #[Package('fundamentals@after-sales')] class Migration1538046469MediaFile extends MigrationStep { diff --git a/src/Core/Migration/Migration1538985581Logging.php b/src/Core/Migration/Migration1538985581Logging.php index 601dc5a45..07ecbb049 100644 --- a/src/Core/Migration/Migration1538985581Logging.php +++ b/src/Core/Migration/Migration1538985581Logging.php @@ -11,6 +11,9 @@ use Shopware\Core\Framework\Log\Package; use Shopware\Core\Framework\Migration\MigrationStep; +/** + * @internal + */ #[Package('fundamentals@after-sales')] class Migration1538985581Logging extends MigrationStep { diff --git a/src/Core/Migration/Migration1544535797GeneralSetting.php b/src/Core/Migration/Migration1544535797GeneralSetting.php index 73aa240aa..6e7e11b09 100644 --- a/src/Core/Migration/Migration1544535797GeneralSetting.php +++ b/src/Core/Migration/Migration1544535797GeneralSetting.php @@ -11,6 +11,9 @@ use Shopware\Core\Framework\Log\Package; use Shopware\Core\Framework\Migration\MigrationStep; +/** + * @internal + */ #[Package('fundamentals@after-sales')] class Migration1544535797GeneralSetting extends MigrationStep { diff --git a/src/Core/Migration/Migration1563456847CleanupLogging.php b/src/Core/Migration/Migration1563456847CleanupLogging.php index 08504c2a9..d36be8530 100644 --- a/src/Core/Migration/Migration1563456847CleanupLogging.php +++ b/src/Core/Migration/Migration1563456847CleanupLogging.php @@ -11,6 +11,9 @@ use Shopware\Core\Framework\Log\Package; use Shopware\Core\Framework\Migration\MigrationStep; +/** + * @internal + */ #[Package('fundamentals@after-sales')] class Migration1563456847CleanupLogging extends MigrationStep { diff --git a/src/Core/Migration/Migration1564041870AddConnectionKeyToMapping.php b/src/Core/Migration/Migration1564041870AddConnectionKeyToMapping.php index 633a6d3c5..2e8c319ec 100644 --- a/src/Core/Migration/Migration1564041870AddConnectionKeyToMapping.php +++ b/src/Core/Migration/Migration1564041870AddConnectionKeyToMapping.php @@ -11,6 +11,9 @@ use Shopware\Core\Framework\Log\Package; use Shopware\Core\Framework\Migration\MigrationStep; +/** + * @internal + */ #[Package('fundamentals@after-sales')] class Migration1564041870AddConnectionKeyToMapping extends MigrationStep { diff --git a/src/Core/Migration/Migration1564053392AddConvertFailureKeyToData.php b/src/Core/Migration/Migration1564053392AddConvertFailureKeyToData.php index c610ca833..f1c74eac6 100644 --- a/src/Core/Migration/Migration1564053392AddConvertFailureKeyToData.php +++ b/src/Core/Migration/Migration1564053392AddConvertFailureKeyToData.php @@ -11,6 +11,9 @@ use Shopware\Core\Framework\Log\Package; use Shopware\Core\Framework\Migration\MigrationStep; +/** + * @internal + */ #[Package('fundamentals@after-sales')] class Migration1564053392AddConvertFailureKeyToData extends MigrationStep { diff --git a/src/Core/Migration/Migration1568882302AddMappingReferenceToData.php b/src/Core/Migration/Migration1568882302AddMappingReferenceToData.php index 6b1c617e0..9d374b932 100644 --- a/src/Core/Migration/Migration1568882302AddMappingReferenceToData.php +++ b/src/Core/Migration/Migration1568882302AddMappingReferenceToData.php @@ -11,6 +11,9 @@ use Shopware\Core\Framework\Log\Package; use Shopware\Core\Framework\Migration\MigrationStep; +/** + * @internal + */ #[Package('fundamentals@after-sales')] class Migration1568882302AddMappingReferenceToData extends MigrationStep { diff --git a/src/Core/Migration/Migration1568882317AddChecksumToMapping.php b/src/Core/Migration/Migration1568882317AddChecksumToMapping.php index bdadc504c..0c0000be2 100644 --- a/src/Core/Migration/Migration1568882317AddChecksumToMapping.php +++ b/src/Core/Migration/Migration1568882317AddChecksumToMapping.php @@ -11,6 +11,9 @@ use Shopware\Core\Framework\Log\Package; use Shopware\Core\Framework\Migration\MigrationStep; +/** + * @internal + */ #[Package('fundamentals@after-sales')] class Migration1568882317AddChecksumToMapping extends MigrationStep { diff --git a/src/Core/Migration/Migration1587476616DeleteOldMappings.php b/src/Core/Migration/Migration1587476616DeleteOldMappings.php index 01a3dd6b2..56a9fec7a 100644 --- a/src/Core/Migration/Migration1587476616DeleteOldMappings.php +++ b/src/Core/Migration/Migration1587476616DeleteOldMappings.php @@ -11,6 +11,9 @@ use Shopware\Core\Framework\Log\Package; use Shopware\Core\Framework\Migration\MigrationStep; +/** + * @internal + */ #[Package('fundamentals@after-sales')] class Migration1587476616DeleteOldMappings extends MigrationStep { diff --git a/src/Core/Migration/Migration1589448383AddIsResetColumnToSetting.php b/src/Core/Migration/Migration1589448383AddIsResetColumnToSetting.php index 23c9c0614..cf775a062 100644 --- a/src/Core/Migration/Migration1589448383AddIsResetColumnToSetting.php +++ b/src/Core/Migration/Migration1589448383AddIsResetColumnToSetting.php @@ -11,6 +11,9 @@ use Shopware\Core\Framework\Log\Package; use Shopware\Core\Framework\Migration\MigrationStep; +/** + * @internal + */ #[Package('fundamentals@after-sales')] class Migration1589448383AddIsResetColumnToSetting extends MigrationStep { diff --git a/src/Core/Migration/Migration1593494859AddEntityUuidConnectionKeyToMapping.php b/src/Core/Migration/Migration1593494859AddEntityUuidConnectionKeyToMapping.php index 6519941ee..fe7062e16 100644 --- a/src/Core/Migration/Migration1593494859AddEntityUuidConnectionKeyToMapping.php +++ b/src/Core/Migration/Migration1593494859AddEntityUuidConnectionKeyToMapping.php @@ -11,6 +11,9 @@ use Shopware\Core\Framework\Log\Package; use Shopware\Core\Framework\Migration\MigrationStep; +/** + * @internal + */ #[Package('fundamentals@after-sales')] class Migration1593494859AddEntityUuidConnectionKeyToMapping extends MigrationStep { diff --git a/src/Core/Migration/Migration1593508853AddMappingUuidKeyToData.php b/src/Core/Migration/Migration1593508853AddMappingUuidKeyToData.php index 4f55484e9..ee0710923 100644 --- a/src/Core/Migration/Migration1593508853AddMappingUuidKeyToData.php +++ b/src/Core/Migration/Migration1593508853AddMappingUuidKeyToData.php @@ -11,6 +11,9 @@ use Shopware\Core\Framework\Log\Package; use Shopware\Core\Framework\Migration\MigrationStep; +/** + * @internal + */ #[Package('fundamentals@after-sales')] class Migration1593508853AddMappingUuidKeyToData extends MigrationStep { diff --git a/src/Core/Migration/Migration1615794849ChangeLengthsOfLoggingColumns.php b/src/Core/Migration/Migration1615794849ChangeLengthsOfLoggingColumns.php index 01cb39660..08c523aa9 100644 --- a/src/Core/Migration/Migration1615794849ChangeLengthsOfLoggingColumns.php +++ b/src/Core/Migration/Migration1615794849ChangeLengthsOfLoggingColumns.php @@ -11,6 +11,9 @@ use Shopware\Core\Framework\Log\Package; use Shopware\Core\Framework\Migration\MigrationStep; +/** + * @internal + */ #[Package('fundamentals@after-sales')] class Migration1615794849ChangeLengthsOfLoggingColumns extends MigrationStep { diff --git a/src/Core/Migration/Migration1701426268RenameProfileInConnections.php b/src/Core/Migration/Migration1701426268RenameProfileInConnections.php index 445c6df96..79f4a88f3 100644 --- a/src/Core/Migration/Migration1701426268RenameProfileInConnections.php +++ b/src/Core/Migration/Migration1701426268RenameProfileInConnections.php @@ -11,6 +11,9 @@ use Shopware\Core\Framework\Log\Package; use Shopware\Core\Framework\Migration\MigrationStep; +/** + * @internal + */ #[Package('fundamentals@after-sales')] class Migration1701426268RenameProfileInConnections extends MigrationStep { diff --git a/src/Core/Migration/Migration1754896654TruncateMigrationLogs.php b/src/Core/Migration/Migration1754896654TruncateMigrationLogs.php new file mode 100644 index 000000000..76077ebaf --- /dev/null +++ b/src/Core/Migration/Migration1754896654TruncateMigrationLogs.php @@ -0,0 +1,29 @@ + + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace SwagMigrationAssistant\Core\Migration; + +use Doctrine\DBAL\Connection; +use Shopware\Core\Framework\Log\Package; +use Shopware\Core\Framework\Migration\MigrationStep; + +/** + * @internal + */ +#[Package('fundamentals@after-sales')] +class Migration1754896654TruncateMigrationLogs extends MigrationStep +{ + public function getCreationTimestamp(): int + { + return 1754896654; + } + + public function update(Connection $connection): void + { + $connection->executeStatement('TRUNCATE TABLE `swag_migration_logging`'); + } +} diff --git a/src/Core/Migration/Migration1754897550AddFieldsToMigrationLogs.php b/src/Core/Migration/Migration1754897550AddFieldsToMigrationLogs.php new file mode 100644 index 000000000..5cc64860a --- /dev/null +++ b/src/Core/Migration/Migration1754897550AddFieldsToMigrationLogs.php @@ -0,0 +1,198 @@ + + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace SwagMigrationAssistant\Core\Migration; + +use Doctrine\DBAL\Connection; +use Doctrine\DBAL\Exception; +use Doctrine\DBAL\Platforms\MySQLPlatform; +use Doctrine\DBAL\Schema\AbstractSchemaManager; +use Shopware\Core\Framework\Log\Package; +use Shopware\Core\Framework\Migration\MigrationStep; + +/** + * @internal + */ +#[Package('fundamentals@after-sales')] +class Migration1754897550AddFieldsToMigrationLogs extends MigrationStep +{ + public const MIGRATION_LOGGING_TABLE = 'swag_migration_logging'; + + public const REQUIRED_FIELDS = [ + 'id' => 'BINARY(16) NOT NULL', + 'run_id' => 'BINARY(16) NULL', + 'profile_name' => 'VARCHAR(64) NOT NULL', + 'gateway_name' => 'VARCHAR(64) NOT NULL', + 'level' => 'VARCHAR(64) NOT NULL', + 'code' => 'VARCHAR(255) NOT NULL', + 'user_fixable' => 'TINYINT(1) NOT NULL DEFAULT 0', + ]; + + public const OPTIONAL_FIELDS = [ + 'entity_name' => 'VARCHAR(64) NULL', + 'entity_id' => 'BINARY(16) NULL', + 'field_name' => 'VARCHAR(64) NULL', + 'field_source_path' => 'VARCHAR(255) NULL', + 'source_data' => 'JSON NULL', + 'converted_data' => 'JSON NULL', + 'exception_message' => 'VARCHAR(255) NULL', + 'exception_trace' => 'JSON NULL', + ]; + + public const SYSTEM_FIELDS = [ + 'auto_increment' => 'BIGINT UNSIGNED AUTO_INCREMENT UNIQUE', + 'created_at' => 'DATETIME(3) NOT NULL', + 'updated_at' => 'DATETIME(3) NULL', + ]; + + public const FIELDS_TO_DROP = [ + 'title', + 'description', + 'parameters', + 'title_snippet', + 'description_snippet', + 'entity', + 'source_id', + ]; + + public function getCreationTimestamp(): int + { + return 1754897550; + } + + /** + * @throws \Throwable + */ + public function update(Connection $connection): void + { + $schemaManager = $connection->createSchemaManager(); + + if (!$schemaManager->tablesExist([self::MIGRATION_LOGGING_TABLE])) { + return; + } + + $this->dropForeignKeyIfExists($connection, self::MIGRATION_LOGGING_TABLE, 'fk.swag_migration_logging.run_id'); + $this->dropIndexIfExists($connection, self::MIGRATION_LOGGING_TABLE, 'idx.swag_migration_logging.run_id_code'); + $this->dropConstraintIfExists($connection, 'json.swag_migration_logging.log_entry'); + + $this->dropObsoleteColumns($connection); + $this->addOrModifyColumns($connection, $schemaManager); + $this->ensureRelations($connection, $schemaManager); + } + + private function dropObsoleteColumns(Connection $connection): void + { + foreach (self::FIELDS_TO_DROP as $column) { + $this->dropColumnIfExists($connection, 'swag_migration_logging', $column); + } + } + + /** + * @param AbstractSchemaManager $schemaManager + */ + private function addOrModifyColumns(Connection $connection, AbstractSchemaManager $schemaManager): void + { + $columns = $schemaManager->listTableColumns(self::MIGRATION_LOGGING_TABLE); + + $orderedFields = array_merge( + self::REQUIRED_FIELDS, + self::OPTIONAL_FIELDS, + self::SYSTEM_FIELDS + ); + + foreach ($orderedFields as $name => $type) { + if (!isset($columns[$name])) { + $connection->executeStatement( + \sprintf( + 'ALTER TABLE `%s` ADD COLUMN `%s` %s;', + self::MIGRATION_LOGGING_TABLE, + $name, + $type + ) + ); + } else { + $connection->executeStatement( + \sprintf( + 'ALTER TABLE `%s` MODIFY COLUMN `%s` %s;', + self::MIGRATION_LOGGING_TABLE, + $name, + $type + ) + ); + } + } + } + + /** + * @param AbstractSchemaManager $schemaManager + */ + private function ensureRelations(Connection $connection, AbstractSchemaManager $schemaManager): void + { + // ensure primary key and index + $indexes = $schemaManager->listTableIndexes(self::MIGRATION_LOGGING_TABLE); + + if (isset($indexes['primary'])) { + $connection->executeStatement( + \sprintf( + 'ALTER TABLE `%s` DROP PRIMARY KEY;', + self::MIGRATION_LOGGING_TABLE + ) + ); + } + + $connection->executeStatement( + \sprintf( + 'ALTER TABLE `%s` ADD PRIMARY KEY (`id`);', + self::MIGRATION_LOGGING_TABLE + ) + ); + + $this->dropIndexIfExists( + $connection, + self::MIGRATION_LOGGING_TABLE, + 'idx.run_id' + ); + $connection->executeStatement( + \sprintf( + 'ALTER TABLE `%s` ADD INDEX `idx.run_id` (`run_id`);', + self::MIGRATION_LOGGING_TABLE + ) + ); + + // ensure entity_id index + if (!$this->indexExists($connection, self::MIGRATION_LOGGING_TABLE, 'idx.entity_id')) { + $connection->executeStatement( + \sprintf( + 'ALTER TABLE `%s` ADD INDEX `idx.entity_id` (`entity_id`);', + self::MIGRATION_LOGGING_TABLE + ) + ); + } + + // ensure foreign key constraint + $connection->executeStatement( + \sprintf( + 'ALTER TABLE `%s` ADD CONSTRAINT `fk.swag_migration_logging.run_id` FOREIGN KEY (`run_id`) REFERENCES `swag_migration_run` (`id`) ON DELETE RESTRICT ON UPDATE CASCADE;', + self::MIGRATION_LOGGING_TABLE + ) + ); + } + + private function dropConstraintIfExists(Connection $connection, string $constraintName): void + { + try { + $connection->executeStatement( + \sprintf( + 'ALTER TABLE `%s` DROP CONSTRAINT `%s`;', + self::MIGRATION_LOGGING_TABLE, + $constraintName + ) + ); + } catch (Exception) { + } + } +} diff --git a/src/Core/Migration/Migration1757598733AddMigrationFixesTable.php b/src/Core/Migration/Migration1757598733AddMigrationFixesTable.php new file mode 100644 index 000000000..8d2b23c5a --- /dev/null +++ b/src/Core/Migration/Migration1757598733AddMigrationFixesTable.php @@ -0,0 +1,57 @@ + + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace SwagMigrationAssistant\Core\Migration; + +use Doctrine\DBAL\Connection; +use Shopware\Core\Framework\Log\Package; +use Shopware\Core\Framework\Migration\MigrationStep; + +/** + * @internal + */ +#[Package('fundamentals@after-sales')] +class Migration1757598733AddMigrationFixesTable extends MigrationStep +{ + public const MIGRATION_FIXES_TABLE = 'swag_migration_fix'; + + public const FIELDS = [ + 'id' => 'BINARY(16) NOT NULL', + 'connection_id' => 'BINARY(16) NOT NULL', + 'value' => 'JSON NOT NULL', + 'path' => 'VARCHAR(255) NOT NULL', + 'entity_name' => 'VARCHAR(255) NULL', + 'entity_id' => 'BINARY(16) NULL', + 'created_at' => 'DATETIME(3) NOT NULL', + 'updated_at' => 'DATETIME(3) NULL', + ]; + + public function getCreationTimestamp(): int + { + return 1757598733; + } + + public function update(Connection $connection): void + { + $columns = []; + + foreach (self::FIELDS as $name => $definition) { + $columns[] = "`$name` $definition"; + } + + $sql = \sprintf(' + CREATE TABLE IF NOT EXISTS `%s` ( + %s, + PRIMARY KEY (`id`), + CONSTRAINT `fk.swag_migration_fix.connection_id` FOREIGN KEY (`connection_id`) REFERENCES `swag_migration_connection` (`id`) ON DELETE CASCADE, + INDEX `idx.entity_id` (`entity_id`) + ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + ', self::MIGRATION_FIXES_TABLE, implode(', ', $columns)); + + $connection->executeStatement($sql); + } +} diff --git a/src/Core/Migration/Migration1759000000AddIsResettingChecksumsToSetting.php b/src/Core/Migration/Migration1759000000AddIsResettingChecksumsToSetting.php new file mode 100644 index 000000000..90129b02e --- /dev/null +++ b/src/Core/Migration/Migration1759000000AddIsResettingChecksumsToSetting.php @@ -0,0 +1,40 @@ + + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace SwagMigrationAssistant\Core\Migration; + +use Doctrine\DBAL\Connection; +use Shopware\Core\Framework\Log\Package; +use Shopware\Core\Framework\Migration\MigrationStep; + +/** + * @internal + */ +#[Package('fundamentals@after-sales')] +class Migration1759000000AddIsResettingChecksumsToSetting extends MigrationStep +{ + public const TABLE = 'swag_migration_general_setting'; + + public const COLUMN = 'is_resetting_checksums'; + + public function getCreationTimestamp(): int + { + return 1759000000; + } + + public function update(Connection $connection): void + { + $this->addColumn( + connection: $connection, + table: self::TABLE, + column: self::COLUMN, + type: 'TINYINT(1)', + nullable: false, + default: '0' + ); + } +} diff --git a/src/Core/Migration/Migration1762346793RenameColumnOfMappingTable.php b/src/Core/Migration/Migration1762346793RenameColumnOfMappingTable.php new file mode 100644 index 000000000..7466fce56 --- /dev/null +++ b/src/Core/Migration/Migration1762346793RenameColumnOfMappingTable.php @@ -0,0 +1,40 @@ + + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace SwagMigrationAssistant\Core\Migration; + +use Doctrine\DBAL\Connection; +use Shopware\Core\Framework\Log\Package; +use Shopware\Core\Framework\Migration\ColumnExistsTrait; +use Shopware\Core\Framework\Migration\MigrationStep; + +/** + * @internal + */ +#[Package('fundamentals@after-sales')] +class Migration1762346793RenameColumnOfMappingTable extends MigrationStep +{ + use ColumnExistsTrait; + + public function getCreationTimestamp(): int + { + return 1762346793; + } + + public function update(Connection $connection): void + { + if ($this->columnExists($connection, 'swag_migration_mapping', 'entity_id')) { + return; + } + + if (!$this->columnExists($connection, 'swag_migration_mapping', 'entity_uuid')) { + return; + } + + $connection->executeStatement('ALTER TABLE `swag_migration_mapping` CHANGE `entity_uuid` `entity_id` BINARY(16)'); + } +} diff --git a/src/Core/Migration/Migration1764145444AddFingerprintToConnectionTable.php b/src/Core/Migration/Migration1764145444AddFingerprintToConnectionTable.php new file mode 100644 index 000000000..e1eea34e7 --- /dev/null +++ b/src/Core/Migration/Migration1764145444AddFingerprintToConnectionTable.php @@ -0,0 +1,38 @@ + + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace SwagMigrationAssistant\Core\Migration; + +use Doctrine\DBAL\Connection; +use Shopware\Core\Framework\Log\Package; +use Shopware\Core\Framework\Migration\MigrationStep; + +/** + * @internal + */ +#[Package('fundamentals@after-sales')] +class Migration1764145444AddFingerprintToConnectionTable extends MigrationStep +{ + public const TABLE = 'swag_migration_connection'; + + public const COLUMN = 'source_system_fingerprint'; + + public function getCreationTimestamp(): int + { + return 1764145444; + } + + public function update(Connection $connection): void + { + $this->addColumn( + connection: $connection, + table: self::TABLE, + column: self::COLUMN, + type: 'VARCHAR(255)', + ); + } +} diff --git a/src/DataProvider/Provider/Data/OrderProvider.php b/src/DataProvider/Provider/Data/OrderProvider.php index 49742f82f..5b1a367dd 100644 --- a/src/DataProvider/Provider/Data/OrderProvider.php +++ b/src/DataProvider/Provider/Data/OrderProvider.php @@ -66,7 +66,6 @@ public function getProvidedData(int $limit, int $offset, Context $context): arra $row['positionPrice'] ); - // ToDo MIG-902: properly migrate this association if (!empty($row['lineItems'])) { foreach ($row['lineItems'] as &$lineItem) { unset($lineItem['promotionId']); diff --git a/src/DataProvider/Provider/Data/ProductProvider.php b/src/DataProvider/Provider/Data/ProductProvider.php index 15f279c38..a2aff026d 100644 --- a/src/DataProvider/Provider/Data/ProductProvider.php +++ b/src/DataProvider/Provider/Data/ProductProvider.php @@ -86,10 +86,9 @@ public function getProvidedData(int $limit, int $offset, Context $context): arra 'thumbnails', 'thumbnailsRo', 'hasFile', - 'userId', // maybe put back in, if we migrate users - - 'canonicalProductId', // ToDo MIG-900: properly migrate this association in a separate DataSet - 'cmsPageId', // ToDo MIG-901: properly migrate this association in a separate DataSet + 'userId', + 'canonicalProductId', + 'cmsPageId', ]); foreach ($cleanResult as &$product) { diff --git a/src/DataProvider/Service/EnvironmentService.php b/src/DataProvider/Service/EnvironmentService.php index 131301c1c..13ba39071 100644 --- a/src/DataProvider/Service/EnvironmentService.php +++ b/src/DataProvider/Service/EnvironmentService.php @@ -9,6 +9,7 @@ use Shopware\Core\Defaults; use Shopware\Core\Framework\Api\Context\SystemSource; +use Shopware\Core\Framework\App\ShopId\ShopIdProvider; use Shopware\Core\Framework\Context; use Shopware\Core\Framework\DataAbstractionLayer\EntityRepository; use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria; @@ -18,11 +19,14 @@ use Shopware\Core\Framework\Store\Services\StoreClient; use Shopware\Core\System\Currency\CurrencyCollection; use Shopware\Core\System\Language\LanguageCollection; +use Shopware\Core\System\SystemConfig\SystemConfigService; #[Package('fundamentals@after-sales')] class EnvironmentService implements EnvironmentServiceInterface { /** + * @internal + * * @param EntityRepository $currencyRepository * @param EntityRepository $languageRepository */ @@ -33,11 +37,12 @@ public function __construct( private readonly string $shopwareRevision, private readonly StoreClient $storeClient, private readonly AbstractExtensionDataProvider $extensionDataProvider, + private readonly SystemConfigService $systemConfigService, ) { } /** - * @return array> + * @return array|null> */ public function getEnvironmentData(Context $context): array { @@ -72,9 +77,21 @@ public function getEnvironmentData(Context $context): array 'revision' => $this->shopwareRevision, 'additionalData' => [], 'updateAvailable' => $updateAvailable, + 'shopIdV2' => $this->getShopIdV2(), ]; } + private function getShopIdV2(): ?string + { + $response = $this->systemConfigService->get(ShopIdProvider::SHOP_ID_SYSTEM_CONFIG_KEY_V2); + + if (\is_array($response) && isset($response['id'])) { + return $response['id']; + } + + return null; + } + private function isPluginUpdateAvailable(Context $context): bool { $criteria = new Criteria(); diff --git a/src/DependencyInjection/dataProvider.xml b/src/DependencyInjection/dataProvider.xml index 2bb1e8393..4e9d72701 100644 --- a/src/DependencyInjection/dataProvider.xml +++ b/src/DependencyInjection/dataProvider.xml @@ -278,6 +278,7 @@ %kernel.shopware_version_revision% + diff --git a/src/DependencyInjection/entity.xml b/src/DependencyInjection/entity.xml index a74cc13ac..170b23118 100644 --- a/src/DependencyInjection/entity.xml +++ b/src/DependencyInjection/entity.xml @@ -45,5 +45,16 @@ + + + + + + + + + + + diff --git a/src/DependencyInjection/migration.xml b/src/DependencyInjection/migration.xml index b67dc462e..b008b1b85 100644 --- a/src/DependencyInjection/migration.xml +++ b/src/DependencyInjection/migration.xml @@ -185,7 +185,6 @@ - @@ -199,6 +198,10 @@ + + + + @@ -222,6 +225,7 @@ + @@ -232,6 +236,7 @@ + @@ -261,6 +266,10 @@ + + + + @@ -270,6 +279,7 @@ + @@ -278,27 +288,13 @@ + - - - - - - - - - - - - - - - @@ -326,7 +322,7 @@ - + @@ -342,7 +338,14 @@ + + + + + + + @@ -382,7 +385,6 @@ - @@ -418,5 +420,12 @@ + + + + + + + diff --git a/src/DependencyInjection/shopware.xml b/src/DependencyInjection/shopware.xml index b893496aa..77f6e4503 100644 --- a/src/DependencyInjection/shopware.xml +++ b/src/DependencyInjection/shopware.xml @@ -212,8 +212,8 @@ - + + + + + + diff --git a/src/Exception/ConverterNotFoundException.php b/src/Exception/ConverterNotFoundException.php deleted file mode 100644 index 90bfb9c52..000000000 --- a/src/Exception/ConverterNotFoundException.php +++ /dev/null @@ -1,15 +0,0 @@ - - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace SwagMigrationAssistant\Exception; - -use Shopware\Core\Framework\Log\Package; - -#[Package('fundamentals@after-sales')] -class ConverterNotFoundException extends MigrationException -{ -} diff --git a/src/Exception/DataSetNotFoundException.php b/src/Exception/DataSetNotFoundException.php deleted file mode 100644 index ad1a5aa25..000000000 --- a/src/Exception/DataSetNotFoundException.php +++ /dev/null @@ -1,15 +0,0 @@ - - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace SwagMigrationAssistant\Exception; - -use Shopware\Core\Framework\Log\Package; - -#[Package('fundamentals@after-sales')] -class DataSetNotFoundException extends MigrationException -{ -} diff --git a/src/Exception/LocaleNotFoundException.php b/src/Exception/LocaleNotFoundException.php deleted file mode 100644 index 275b51d09..000000000 --- a/src/Exception/LocaleNotFoundException.php +++ /dev/null @@ -1,15 +0,0 @@ - - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace SwagMigrationAssistant\Exception; - -use Shopware\Core\Framework\Log\Package; - -#[Package('fundamentals@after-sales')] -class LocaleNotFoundException extends MigrationException -{ -} diff --git a/src/Exception/MigrationException.php b/src/Exception/MigrationException.php index 5eeee646b..ff1c28442 100644 --- a/src/Exception/MigrationException.php +++ b/src/Exception/MigrationException.php @@ -13,6 +13,9 @@ use Shopware\Core\Framework\Log\Package; use Symfony\Component\HttpFoundation\Response; +/** + * @codeCoverageIgnore + */ #[Package('fundamentals@after-sales')] class MigrationException extends HttpException { @@ -24,81 +27,79 @@ class MigrationException extends HttpException final public const PROVIDER_HAS_NO_TABLE_ACCESS = 'SWAG_MIGRATION__PROVIDER_HAS_NO_TABLE_ACCESS'; - public const MIGRATION_CONTEXT_NOT_CREATED = 'SWAG_MIGRATION__MIGRATION_CONTEXT_NOT_CREATED'; - - public const NO_RUNNING_MIGRATION = 'SWAG_MIGRATION__NO_RUNNING_MIGRATION'; + final public const MIGRATION_CONTEXT_NOT_CREATED = 'SWAG_MIGRATION__MIGRATION_CONTEXT_NOT_CREATED'; - public const NO_RUN_TO_FINISH = 'SWAG_MIGRATION__NO_RUN_TO_FINISH'; + final public const RUN_NOT_FOUND = 'SWAG_MIGRATION__RUN_NOT_FOUND'; - public const MIGRATION_IS_ALREADY_RUNNING = 'SWAG_MIGRATION__MIGRATION_IS_ALREADY_RUNNING'; + final public const NO_RUN_PROGRESS_FOUND = 'SWAG_MIGRATION__NO_RUN_PROGRESS_FOUND'; - public const NO_CONNECTION_IS_SELECTED = 'SWAG_MIGRATION__NO_CONNECTION_IS_SELECTED'; + final public const MIGRATION_PROCESSING = 'SWAG_MIGRATION__MIGRATION_PROCESSING'; - public const NO_CONNECTION_FOUND = 'SWAG_MIGRATION__NO_CONNECTION_FOUND'; + final public const NO_CONNECTION_FOUND = 'SWAG_MIGRATION__NO_CONNECTION_FOUND'; - public const RUN_COULD_NOT_BE_CREATED = 'SWAG_MIGRATION__RUN_COULD_NOT_BE_CREATED'; + final public const RUN_COULD_NOT_BE_CREATED = 'SWAG_MIGRATION__RUN_COULD_NOT_BE_CREATED'; - public const PREMAPPING_IS_INCOMPLETE = 'SWAG_MIGRATION__PREMAPPING_IS_INCOMPLETE'; + final public const PREMAPPING_IS_INCOMPLETE = 'SWAG_MIGRATION__PREMAPPING_IS_INCOMPLETE'; - public const NO_DATA_TO_MIGRATE = 'SWAG_MIGRATION__NO_DATA_TO_MIGRATE'; + final public const NO_DATA_TO_MIGRATE = 'SWAG_MIGRATION__NO_DATA_TO_MIGRATE'; - public const NO_RUN_PROGRESS_FOUND = 'SWAG_MIGRATION__NO_RUN_PROGRESS_FOUND'; + final public const UNKNOWN_PROGRESS_STEP = 'SWAG_MIGRATION__UNKNOWN_PROGRESS_STEP'; - public const UNKNOWN_PROGRESS_STEP = 'SWAG_MIGRATION__UNKNON_PROGRESS_STEP'; + final public const ENTITY_NOT_EXISTS = 'SWAG_MIGRATION__ENTITY_NOT_EXISTS'; - public const ENTITY_NOT_EXISTS = 'SWAG_MIGRATION__ENTITY_NOT_EXISTS'; + final public const PROCESSOR_NOT_FOUND = 'SWAG_MIGRATION__PROCESSOR_NOT_FOUND'; - public const PROCESSOR_NOT_FOUND = 'SWAG_MIGRATION__PROCESSOR_NOT_FOUND'; + final public const INVALID_FIELD_SERIALIZER = 'SWAG_MIGRATION__INVALID_FIELD_SERIALIZER'; - public const INVALID_FIELD_SERIALIZER = 'SWAG_MIGRATION__INVALID_FIELD_SERIALIZER'; + final public const INVALID_CONNECTION_CREDENTIALS = 'SWAG_MIGRATION__INVALID_CONNECTION_CREDENTIALS'; - public const INVALID_CONNECTION_AUTHENTICATION = 'SWAG_MIGRATION__INVALID_CONNECTION_AUTHENTICATION'; + final public const SSL_REQUIRED = 'SWAG_MIGRATION__SSL_REQUIRED'; - public const INVALID_CONNECTION_CREDENTIALS = 'SWAG_MIGRATION__INVALID_CONNECTION_CREDENTIALS'; + final public const REQUEST_CERTIFICATE_INVALID = 'SWAG_MIGRATION__REQUEST_CERTIFICATE_INVALID'; - public const SSL_REQUIRED = 'SWAG_MIGRATION__SSL_REQUIRED'; + final public const CONVERTER_NOT_FOUND = 'SWAG_MIGRATION__CONVERTER_NOT_FOUND'; - public const REQUEST_CERTIFICATE_INVALID = 'SWAG_MIGRATION__REQUEST_CERTIFICATE_INVALID'; + final public const MIGRATION_CONTEXT_PROPERTY_MISSING = 'SWAG_MIGRATION__MIGRATION_CONTEXT_PROPERTY_MISSING'; - public const CONVERTER_NOT_FOUND = 'SWAG_MIGRATION__CONVERTER_NOT_FOUND'; + final public const READER_NOT_FOUND = 'SWAG_MIGRATION__READER_NOT_FOUND'; - public const MIGRATION_CONTEXT_PROPERTY_MISSING = 'SWAG_MIGRATION__MIGRATION_CONTEXT_PROPERTY_MISSING'; + final public const DATASET_NOT_FOUND = 'SWAG_MIGRATION__DATASET_NOT_FOUND'; - public const READER_NOT_FOUND = 'SWAG_MIGRATION__READER_NOT_FOUND'; + final public const LOCALE_NOT_FOUND = 'SWAG_MIGRATION__LOCALE_NOT_FOUND'; - public const DATASET_NOT_FOUND = 'SWAG_MIGRATION__DATASET_NOT_FOUND'; + final public const UNDEFINED_RUN_STATUS = 'SWAG_MIGRATION__UNDEFINED_RUN_STATUS'; - public const LOCALE_NOT_FOUND = 'SWAG_MIGRATION__LOCALE_NOT_FOUND'; + final public const PROFILE_NOT_FOUND = 'SWAG_MIGRATION__PROFILE_NOT_FOUND'; - public const UNDEFINED_RUN_STATUS = 'SWAG_MIGRATION__UNDEFINED_RUN_STATUS'; + final public const WRITER_NOT_FOUND = 'SWAG_MIGRATION__WRITER_NOT_FOUND'; - public const NO_FILE_SYSTEM_PERMISSIONS = 'SWAG_MIGRATION__NO_FILE_SYSTEM_PERMISSIONS'; + final public const COULD_NOT_READ_FILE = 'SWAG_MIGRATION__COULD_NOT_READ_FILE'; - public const PROFILE_NOT_FOUND = 'SWAG_MIGRATION__PROFILE_NOT_FOUND'; + final public const PROVIDER_NOT_FOUND = 'SWAG_MIGRATION__PROVIDER_NOT_FOUND'; - public const WRITER_NOT_FOUND = 'SWAG_MIGRATION__WRITER_NOT_FOUND'; + final public const COULD_NOT_GENERATE_DOCUMENT = 'SWAG_MIGRATION__COULD_NOT_GENERATE_DOCUMENT'; - public const COULD_NOT_READ_FILE = 'SWAG_MIGRATION__COULD_NOT_READ_FILE'; + final public const ASSOCIATION_ENTITY_REQUIRED_MISSING = 'SWAG_MIGRATION__ASSOCIATION_REQUIRED_MISSING'; - public const PROVIDER_NOT_FOUND = 'SWAG_MIGRATION__PROVIDER_NOT_FOUND'; + final public const DATABASE_CONNECTION_ATTRIBUTES_WRONG = 'SWAG_MIGRATION__DATABASE_CONNECTION_ATTRIBUTES_WRONG'; - public const COULD_NOT_GENERATE_DOCUMENT = 'SWAG_MIGRATION__COULD_NOT_GENERATE_DOCUMENT'; + final public const INVALID_WRITE_CONTEXT = 'SWAG_MIGRATION__INVALID_WRITE_CONTEXT'; - public const ASSOCIATION_ENTITY_REQUIRED_MISSING = 'SWAG_MIGRATION__ASSOCIATION_REQUIRED_MISSING'; + final public const API_CONNECTION_ERROR = 'SWAG_MIGRATION__API_CONNECTION_ERROR'; - public const DATABASE_CONNECTION_ERROR = 'SWAG_MIGRATION__DATABASE_CONNECTION_ERROR'; + final public const UNEXPECTED_NULL_VALUE = 'SWAG_MIGRATION__UNEXPECTED_NULL_VALUE'; - public const DATABASE_CONNECTION_ATTRIBUTES_WRONG = 'SWAG_MIGRATION__DATABASE_CONNECTION_ATTRIBUTES_WRONG'; + final public const COULD_NOT_CONVERT_FIX = 'SWAG_MIGRATION__COULD_NOT_CONVERT_FIX'; - public const LOOKUP_LOCALE_FOR_LANGUAGE_LOOKUP_NOT_FOUND = 'SWAG_MIGRATION__LOOKUP_LOCALE_FOR_LANGUAGE_LOOKUP_NOT_FOUND'; + final public const MIGRATION_NOT_IN_STEP = 'SWAG_MIGRATION__MIGRATION_NOT_IN_STEP'; - public const INVALID_WRITE_CONTEXT = 'SWAG_MIGRATION__INVALID_WRITE_CONTEXT'; + final public const INVALID_ID = 'SWAG_MIGRATION__INVALID_ID'; - public const API_CONNECTION_ERROR = 'SWAG_MIGRATION__API_CONNECTION_ERROR'; + public const DUPLICATE_SOURCE_CONNECTION = 'SWAG_MIGRATION__DUPLICATE_SOURCE_CONNECTION'; public static function associationEntityRequiredMissing(string $entity, string $missingEntity): self { - return new AssociationEntityRequiredMissingException( + return new self( Response::HTTP_NOT_FOUND, self::ASSOCIATION_ENTITY_REQUIRED_MISSING, 'Mapping of "{{ missingEntity }}" is missing, but it is a required association for "{{ entity }}". Import "{{ missingEntity }}" first.', @@ -109,15 +110,6 @@ public static function associationEntityRequiredMissing(string $entity, string $ ); } - public static function databaseConnectionError(): self - { - return new self( - Response::HTTP_INTERNAL_SERVER_ERROR, - self::DATABASE_CONNECTION_ERROR, - 'Database connection could not be established.' - ); - } - public static function databaseConnectionAttributesWrong(): self { return new self( @@ -138,8 +130,8 @@ public static function apiConnectionError(string $message): self public static function gatewayRead(string $gateway): self { - return new GatewayReadException( - Response::HTTP_NOT_FOUND, + return new self( + Response::HTTP_BAD_GATEWAY, self::GATEWAY_READ, 'Could not read from gateway: "{{ gateway }}".', ['gateway' => $gateway] @@ -168,7 +160,7 @@ public static function readerNotFound(string $entityName): self public static function dataSetNotFound(string $entity): self { - return new DataSetNotFoundException( + return new self( Response::HTTP_NOT_FOUND, self::DATASET_NOT_FOUND, 'Data set for "{{ entity }}" entity not found.', @@ -176,29 +168,28 @@ public static function dataSetNotFound(string $entity): self ); } - public static function invalidConnectionAuthentication(string $url): self + public static function invalidConnectionCredentials(?string $url = null): self { - return new self( - Response::HTTP_BAD_REQUEST, - self::INVALID_CONNECTION_AUTHENTICATION, - 'Invalid connection authentication for the request: "{{ url }}"', - ['url' => $url] - ); - } + $message = 'The connection credentials are invalid or incomplete.'; + + if ($url !== null) { + $message = \sprintf( + 'The connection credentials are invalid or incomplete for "%s".', + $url + ); + } - public static function invalidConnectionCredentials(): self - { return new self( - Response::HTTP_BAD_REQUEST, + Response::HTTP_UNAUTHORIZED, self::INVALID_CONNECTION_CREDENTIALS, - 'Invalid or missing connection credentials', + $message, ); } public static function sslRequired(): self { return new self( - Response::HTTP_MISDIRECTED_REQUEST, + Response::HTTP_FORBIDDEN, self::SSL_REQUIRED, 'The request failed, because SSL is required.' ); @@ -207,7 +198,7 @@ public static function sslRequired(): self public static function requestCertificateInvalid(string $url): self { return new self( - Response::HTTP_BAD_REQUEST, + Response::HTTP_BAD_GATEWAY, self::REQUEST_CERTIFICATE_INVALID, 'The following cURL request failed with an SSL certificate problem: "{{ url }}"', ['url' => $url] @@ -247,7 +238,7 @@ public static function providerNotFound(string $identifier): self public static function migrationContextNotCreated(): self { return new self( - Response::HTTP_BAD_REQUEST, + Response::HTTP_INTERNAL_SERVER_ERROR, self::MIGRATION_CONTEXT_NOT_CREATED, 'Migration context could not be created.', ); @@ -263,46 +254,45 @@ public static function migrationContextPropertyMissing(string $property): self ); } - public static function noRunningMigration(?string $runUuid = null): self + public static function runNotFound(?string $runId = null): self { - if ($runUuid !== null) { - return new NoRunningMigrationException( - Response::HTTP_BAD_REQUEST, - self::NO_RUNNING_MIGRATION, - 'No running migration found with id: "{{ runUuid }}".', - ['runUuid' => $runUuid] - ); - } - - return new NoRunningMigrationException( - Response::HTTP_BAD_REQUEST, - self::NO_RUNNING_MIGRATION, - 'No running migration found.', + return new self( + Response::HTTP_NOT_FOUND, + self::RUN_NOT_FOUND, + 'No migration run found for run with id: "{{ runUuid }}".', + ['runUuid' => $runId ?? 'unknown'] ); } - public static function migrationIsAlreadyRunning(): self + public static function noRunProgressFound(string $runId): self { - return new MigrationIsAlreadyRunningException( - Response::HTTP_BAD_REQUEST, - self::MIGRATION_IS_ALREADY_RUNNING, - 'Migration is already running.', + return new self( + Response::HTTP_NOT_FOUND, + self::NO_RUN_PROGRESS_FOUND, + 'No progress found for migration run with id: "{{ runUuid }}".', + ['runUuid' => $runId] ); } - public static function noConnectionIsSelected(): self + public static function migrationProcessing(?string $process = null): self { + $message = 'Migration is busy processing.'; + + if ($process !== null) { + $message = \sprintf('Migration is busy processing: "%s".', $process); + } + return new self( - Response::HTTP_BAD_REQUEST, - self::NO_CONNECTION_IS_SELECTED, - 'No connection is selected.', + Response::HTTP_CONFLICT, + self::MIGRATION_PROCESSING, + $message, ); } public static function noConnectionFound(): self { - return new NoConnectionFoundException( - Response::HTTP_BAD_REQUEST, + return new self( + Response::HTTP_NOT_FOUND, self::NO_CONNECTION_FOUND, 'No connection found.', ); @@ -311,24 +301,15 @@ public static function noConnectionFound(): self public static function runCouldNotBeCreated(): self { return new self( - Response::HTTP_BAD_REQUEST, + Response::HTTP_INTERNAL_SERVER_ERROR, self::RUN_COULD_NOT_BE_CREATED, 'Could not created migration run.', ); } - public static function noRunToFinish(): self - { - return new self( - Response::HTTP_BAD_REQUEST, - self::NO_RUN_TO_FINISH, - 'No migration run to finish found.', - ); - } - public static function premappingIsIncomplete(): self { - return new PremappingIsIncompleteException( + return new self( Response::HTTP_BAD_REQUEST, self::PREMAPPING_IS_INCOMPLETE, 'Premapping is incomplete.', @@ -344,16 +325,6 @@ public static function noDataToMigrate(): self ); } - public static function noRunProgressFound(string $runUuid): self - { - return new self( - Response::HTTP_BAD_REQUEST, - self::NO_RUN_PROGRESS_FOUND, - 'No run progress found for run with id: "{{ runUuid }}".', - ['runUuid' => $runUuid] - ); - } - public static function unknownProgressStep(?string $step): self { return new self( @@ -367,7 +338,7 @@ public static function unknownProgressStep(?string $step): self public static function entityNotExists(string $entityClassName, string $uuid): self { return new self( - Response::HTTP_BAD_REQUEST, + Response::HTTP_NOT_FOUND, self::ENTITY_NOT_EXISTS, 'No {{ entityClassName }} with UUID {{ uuid }} found. Make sure the entity with the UUID exists.', [ @@ -393,7 +364,7 @@ public static function processorNotFound(string $profile, string $gateway): self public static function invalidSerializerField(string $expectedClass, Field $field): self { return new self( - Response::HTTP_BAD_REQUEST, + Response::HTTP_INTERNAL_SERVER_ERROR, self::INVALID_FIELD_SERIALIZER, 'Expected field of type "{{ expectedField }}" got "{{ field }}".', ['expectedField' => $expectedClass, 'field' => $field::class] @@ -412,7 +383,7 @@ public static function converterNotFound(string $entity): self public static function localeNotFound(string $localeCode): self { - return new LocaleNotFoundException( + return new self( Response::HTTP_NOT_FOUND, self::LOCALE_NOT_FOUND, 'Locale entity for code "{{ localeCode }}" not found.', @@ -430,15 +401,6 @@ public static function undefinedRunStatus(string $status): self ); } - public static function noFileSystemPermissions(): self - { - return new self( - Response::HTTP_INTERNAL_SERVER_ERROR, - self::NO_FILE_SYSTEM_PERMISSIONS, - 'No file system permissions to create or write to files or directories.' - ); - } - public static function profileNotFound(string $profileName): self { return new self( @@ -451,7 +413,7 @@ public static function profileNotFound(string $profileName): self public static function writerNotFound(string $entityName): self { - return new WriterNotFoundException( + return new self( Response::HTTP_NOT_FOUND, self::WRITER_NOT_FOUND, 'Writer for "{{ entityName }}" entity not found.', @@ -478,16 +440,6 @@ public static function couldNotGenerateDocument(): self ); } - public static function localeForLanguageLookupNotFound(string $localeCode): self - { - return new self( - Response::HTTP_NOT_FOUND, - self::LOOKUP_LOCALE_FOR_LANGUAGE_LOOKUP_NOT_FOUND, - 'Locale with code: "{{ localeCode }}" for language lookup not found.', - ['localeCode' => $localeCode] - ); - } - public static function invalidWriteContext(Context $invalidContext): self { return new self( @@ -499,4 +451,53 @@ public static function invalidWriteContext(Context $invalidContext): self ] ); } + + public static function unexpectedNullValue(string $fieldName): self + { + return new self( + Response::HTTP_INTERNAL_SERVER_ERROR, + self::UNEXPECTED_NULL_VALUE, + 'Unexpected null value for field "{{ fieldName }}".', + ['fieldName' => $fieldName] + ); + } + + public static function couldNotConvertFix(string $missingKey): self + { + return new self( + Response::HTTP_INTERNAL_SERVER_ERROR, + self::COULD_NOT_CONVERT_FIX, + 'Missing key "{{ missingKey }}" to construct MigrationFix.', + ['missingKey' => $missingKey] + ); + } + + public static function migrationNotInStep(string $runUuid, string $step): self + { + return new self( + Response::HTTP_CONFLICT, + self::MIGRATION_NOT_IN_STEP, + 'Migration with id: "{{ runUuid }}" is not in step "{{ step }}".', + ['runUuid' => $runUuid, 'step' => $step] + ); + } + + public static function invalidId(string $entityId, string $entityName): self + { + return new self( + Response::HTTP_INTERNAL_SERVER_ERROR, + self::INVALID_ID, + 'The id "{{ entityId }}" for entity "{{ entityName }}" is not a valid Uuid', + ['entityId' => $entityId, 'entityName' => $entityName] + ); + } + + public static function duplicateSourceConnection(): self + { + return new self( + Response::HTTP_CONFLICT, + self::DUPLICATE_SOURCE_CONNECTION, + 'A connection to this source system already exists.', + ); + } } diff --git a/src/Exception/MigrationIsAlreadyRunningException.php b/src/Exception/MigrationIsAlreadyRunningException.php deleted file mode 100644 index 3d6fb2801..000000000 --- a/src/Exception/MigrationIsAlreadyRunningException.php +++ /dev/null @@ -1,15 +0,0 @@ - - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace SwagMigrationAssistant\Exception; - -use Shopware\Core\Framework\Log\Package; - -#[Package('fundamentals@after-sales')] -class MigrationIsAlreadyRunningException extends MigrationException -{ -} diff --git a/src/Exception/NoConnectionFoundException.php b/src/Exception/NoConnectionFoundException.php deleted file mode 100644 index 033a8a98f..000000000 --- a/src/Exception/NoConnectionFoundException.php +++ /dev/null @@ -1,15 +0,0 @@ - - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace SwagMigrationAssistant\Exception; - -use Shopware\Core\Framework\Log\Package; - -#[Package('fundamentals@after-sales')] -class NoConnectionFoundException extends MigrationException -{ -} diff --git a/src/Exception/NoRunningMigrationException.php b/src/Exception/NoRunningMigrationException.php deleted file mode 100644 index 1c212e9aa..000000000 --- a/src/Exception/NoRunningMigrationException.php +++ /dev/null @@ -1,15 +0,0 @@ - - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace SwagMigrationAssistant\Exception; - -use Shopware\Core\Framework\Log\Package; - -#[Package('fundamentals@after-sales')] -class NoRunningMigrationException extends MigrationException -{ -} diff --git a/src/Exception/PremappingIsIncompleteException.php b/src/Exception/PremappingIsIncompleteException.php deleted file mode 100644 index 6eab74073..000000000 --- a/src/Exception/PremappingIsIncompleteException.php +++ /dev/null @@ -1,15 +0,0 @@ - - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace SwagMigrationAssistant\Exception; - -use Shopware\Core\Framework\Log\Package; - -#[Package('fundamentals@after-sales')] -class PremappingIsIncompleteException extends MigrationException -{ -} diff --git a/src/Exception/WriterNotFoundException.php b/src/Exception/WriterNotFoundException.php deleted file mode 100644 index 1bc8ed537..000000000 --- a/src/Exception/WriterNotFoundException.php +++ /dev/null @@ -1,15 +0,0 @@ - - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace SwagMigrationAssistant\Exception; - -use Shopware\Core\Framework\Log\Package; - -#[Package('fundamentals@after-sales')] -class WriterNotFoundException extends MigrationException -{ -} diff --git a/src/Migration/Connection/Fingerprint/MigrationFingerprintService.php b/src/Migration/Connection/Fingerprint/MigrationFingerprintService.php new file mode 100644 index 000000000..f71407479 --- /dev/null +++ b/src/Migration/Connection/Fingerprint/MigrationFingerprintService.php @@ -0,0 +1,49 @@ + + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace SwagMigrationAssistant\Migration\Connection\Fingerprint; + +use Shopware\Core\Framework\Context; +use Shopware\Core\Framework\DataAbstractionLayer\EntityRepository; +use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria; +use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsFilter; +use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\MultiFilter; +use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\NotFilter; +use Shopware\Core\Framework\Log\Package; +use SwagMigrationAssistant\Migration\Connection\SwagMigrationConnectionCollection; + +#[Package('fundamentals@after-sales')] +readonly class MigrationFingerprintService implements MigrationFingerprintServiceInterface +{ + /** + * @internal + * + * @param EntityRepository $connectionRepo + */ + public function __construct( + private EntityRepository $connectionRepo, + ) { + } + + public function searchDuplicates(?string $fingerprint, Context $context, ?string $excludeConnectionId): bool + { + if (empty($fingerprint)) { + return false; + } + + $criteria = new Criteria(); + $criteria->addFilter(new EqualsFilter('sourceSystemFingerprint', $fingerprint)); + + if (isset($excludeConnectionId)) { + $criteria->addFilter(new NotFilter(MultiFilter::CONNECTION_AND, [ + new EqualsFilter('id', $excludeConnectionId), + ])); + } + + return $this->connectionRepo->searchIds($criteria, $context)->getTotal() > 0; + } +} diff --git a/src/Exception/AssociationEntityRequiredMissingException.php b/src/Migration/Connection/Fingerprint/MigrationFingerprintServiceInterface.php similarity index 52% rename from src/Exception/AssociationEntityRequiredMissingException.php rename to src/Migration/Connection/Fingerprint/MigrationFingerprintServiceInterface.php index 25503516f..25c718c59 100644 --- a/src/Exception/AssociationEntityRequiredMissingException.php +++ b/src/Migration/Connection/Fingerprint/MigrationFingerprintServiceInterface.php @@ -5,11 +5,13 @@ * file that was distributed with this source code. */ -namespace SwagMigrationAssistant\Exception; +namespace SwagMigrationAssistant\Migration\Connection\Fingerprint; +use Shopware\Core\Framework\Context; use Shopware\Core\Framework\Log\Package; #[Package('fundamentals@after-sales')] -class AssociationEntityRequiredMissingException extends MigrationException +interface MigrationFingerprintServiceInterface { + public function searchDuplicates(?string $fingerprint, Context $context, ?string $excludeConnectionId): bool; } diff --git a/src/Migration/Connection/Helper/ConnectionNameSanitizer.php b/src/Migration/Connection/Helper/ConnectionNameSanitizer.php index a8b72e073..c1c3538e9 100644 --- a/src/Migration/Connection/Helper/ConnectionNameSanitizer.php +++ b/src/Migration/Connection/Helper/ConnectionNameSanitizer.php @@ -9,8 +9,11 @@ use Shopware\Core\Framework\Log\Package; +/** + * @internal + */ #[Package('fundamentals@after-sales')] -class ConnectionNameSanitizer +readonly class ConnectionNameSanitizer { /** * Sanitizes the connection name by removing any special characters, hyphens and spaces. diff --git a/src/Migration/Connection/SwagMigrationConnectionDefinition.php b/src/Migration/Connection/SwagMigrationConnectionDefinition.php index eebe9b006..41d8e9431 100644 --- a/src/Migration/Connection/SwagMigrationConnectionDefinition.php +++ b/src/Migration/Connection/SwagMigrationConnectionDefinition.php @@ -54,6 +54,7 @@ protected function defineFields(): FieldCollection new PremappingField('premapping', 'premapping'), (new StringField('profile_name', 'profileName'))->addFlags(new Required()), (new StringField('gateway_name', 'gatewayName'))->addFlags(new Required()), + new StringField('source_system_fingerprint', 'sourceSystemFingerprint'), new CreatedAtField(), new UpdatedAtField(), new OneToManyAssociationField('runs', SwagMigrationRunDefinition::class, 'connection_id'), diff --git a/src/Migration/Connection/SwagMigrationConnectionEntity.php b/src/Migration/Connection/SwagMigrationConnectionEntity.php index 9982f6adf..5197bccb9 100644 --- a/src/Migration/Connection/SwagMigrationConnectionEntity.php +++ b/src/Migration/Connection/SwagMigrationConnectionEntity.php @@ -36,6 +36,8 @@ class SwagMigrationConnectionEntity extends Entity protected string $gatewayName = ''; + protected ?string $sourceSystemFingerprint = null; + protected ?SwagMigrationRunCollection $runs = null; protected ?SwagMigrationMappingCollection $mappings = null; @@ -104,6 +106,16 @@ public function setGatewayName(string $gatewayName): void $this->gatewayName = $gatewayName; } + public function getSourceSystemFingerprint(): ?string + { + return $this->sourceSystemFingerprint; + } + + public function setSourceSystemFingerprint(string $sourceSystemFingerprint): void + { + $this->sourceSystemFingerprint = $sourceSystemFingerprint; + } + public function getRuns(): ?SwagMigrationRunCollection { return $this->runs; diff --git a/src/Migration/Converter/Converter.php b/src/Migration/Converter/Converter.php index 5c4ee2cc2..4945a31ed 100644 --- a/src/Migration/Converter/Converter.php +++ b/src/Migration/Converter/Converter.php @@ -9,6 +9,7 @@ use Shopware\Core\Framework\Context; use Shopware\Core\Framework\Log\Package; +use Shopware\Core\Framework\Util\Hasher; use SwagMigrationAssistant\Migration\Logging\LoggingServiceInterface; use SwagMigrationAssistant\Migration\Mapping\MappingServiceInterface; use SwagMigrationAssistant\Migration\MigrationContextInterface; @@ -21,7 +22,7 @@ abstract class Converter implements ConverterInterface protected LoggingServiceInterface $loggingService; /** - * @var ?array{id: string, connectionId: string, oldIdentifier: ?string, entityUuid: ?string, entityValue: ?string, checksum: ?string, additionalData: ?array} + * @var ?array{id: string, connectionId: string, oldIdentifier: ?string, entityId: ?string, entityValue: ?string, checksum: ?string, additionalData: ?array} */ protected ?array $mainMapping = null; @@ -58,7 +59,7 @@ public function getMediaUuids(array $converted): ?array */ protected function generateChecksum(array $data): void { - $this->checksum = \md5(\serialize($data)); + $this->checksum = Hasher::hash(\serialize($data)); } /** @@ -70,13 +71,18 @@ protected function updateMainMapping(MigrationContextInterface $migrationContext return; } + if (!\is_array($this->mainMapping['additionalData'] ?? null)) { + $this->mainMapping['additionalData'] = []; + } + $this->mainMapping['checksum'] = $this->checksum; $this->mainMapping['additionalData']['relatedMappings'] = $this->mappingIds; $this->mappingIds = []; $dataSet = $migrationContext->getDataSet(); $connection = $migrationContext->getConnection(); - if ($dataSet === null || $connection === null) { + + if ($dataSet === null) { return; } diff --git a/src/Migration/Converter/ConverterInterface.php b/src/Migration/Converter/ConverterInterface.php index 1a83d4f89..6850b75bd 100644 --- a/src/Migration/Converter/ConverterInterface.php +++ b/src/Migration/Converter/ConverterInterface.php @@ -38,9 +38,11 @@ public function getMediaUuids(array $converted): ?array; /** * Converts the given data into the internal structure * + * A converter also could return null in various cases + * * @param array $data */ - public function convert(array $data, Context $context, MigrationContextInterface $migrationContext): ConvertStruct; + public function convert(array $data, Context $context, MigrationContextInterface $migrationContext): ?ConvertStruct; public function writeMapping(Context $context): void; } diff --git a/src/Migration/Converter/ConverterRegistry.php b/src/Migration/Converter/ConverterRegistry.php index 77a328830..77fbe39a3 100644 --- a/src/Migration/Converter/ConverterRegistry.php +++ b/src/Migration/Converter/ConverterRegistry.php @@ -8,7 +8,6 @@ namespace SwagMigrationAssistant\Migration\Converter; use Shopware\Core\Framework\Log\Package; -use SwagMigrationAssistant\Exception\ConverterNotFoundException; use SwagMigrationAssistant\Exception\MigrationException; use SwagMigrationAssistant\Migration\MigrationContextInterface; @@ -23,7 +22,7 @@ public function __construct(private readonly iterable $converters) } /** - * @throws ConverterNotFoundException + * @throws MigrationException */ public function getConverter(MigrationContextInterface $migrationContext): ConverterInterface { @@ -33,11 +32,6 @@ public function getConverter(MigrationContextInterface $migrationContext): Conve } } - $connection = $migrationContext->getConnection(); - if ($connection === null) { - throw MigrationException::migrationContextPropertyMissing('Connection'); - } - - throw MigrationException::converterNotFound($connection->getProfileName()); + throw MigrationException::converterNotFound($migrationContext->getProfile()->getName()); } } diff --git a/src/Migration/DataSelection/DataSet/DataSetRegistryInterface.php b/src/Migration/DataSelection/DataSet/DataSetRegistryInterface.php index ae3e24ada..38346c235 100644 --- a/src/Migration/DataSelection/DataSet/DataSetRegistryInterface.php +++ b/src/Migration/DataSelection/DataSet/DataSetRegistryInterface.php @@ -8,7 +8,7 @@ namespace SwagMigrationAssistant\Migration\DataSelection\DataSet; use Shopware\Core\Framework\Log\Package; -use SwagMigrationAssistant\Exception\DataSetNotFoundException; +use SwagMigrationAssistant\Exception\MigrationException; use SwagMigrationAssistant\Migration\MigrationContextInterface; #[Package('fundamentals@after-sales')] @@ -20,7 +20,7 @@ interface DataSetRegistryInterface public function getDataSets(MigrationContextInterface $migrationContext): array; /** - * @throws DataSetNotFoundException + * @throws MigrationException */ public function getDataSet(MigrationContextInterface $migrationContext, string $dataSetName): DataSet; } diff --git a/src/Migration/EnvironmentInformation.php b/src/Migration/EnvironmentInformation.php index 3fb42e92e..b7176d235 100644 --- a/src/Migration/EnvironmentInformation.php +++ b/src/Migration/EnvironmentInformation.php @@ -31,6 +31,7 @@ public function __construct( protected string $sourceSystemCurrency = '', protected string $sourceSystemLocale = '', protected string $targetSystemLocale = '', + protected ?string $fingerprint = null, ) { } @@ -112,4 +113,14 @@ public function setTargetSystemLocale(string $targetSystemLocale): void { $this->targetSystemLocale = $targetSystemLocale; } + + public function getFingerprint(): ?string + { + return $this->fingerprint; + } + + public function setFingerprint(?string $fingerprint): void + { + $this->fingerprint = $fingerprint; + } } diff --git a/src/Migration/ErrorResolution/Entity/SwagMigrationFixCollection.php b/src/Migration/ErrorResolution/Entity/SwagMigrationFixCollection.php new file mode 100644 index 000000000..70b0f2fc3 --- /dev/null +++ b/src/Migration/ErrorResolution/Entity/SwagMigrationFixCollection.php @@ -0,0 +1,23 @@ + + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace SwagMigrationAssistant\Migration\ErrorResolution\Entity; + +use Shopware\Core\Framework\DataAbstractionLayer\EntityCollection; +use Shopware\Core\Framework\Log\Package; + +/** + * @extends EntityCollection + */ +#[Package('fundamentals@after-sales')] +class SwagMigrationFixCollection extends EntityCollection +{ + protected function getExpectedClass(): string + { + return SwagMigrationFixEntity::class; + } +} diff --git a/src/Migration/ErrorResolution/Entity/SwagMigrationFixDefinition.php b/src/Migration/ErrorResolution/Entity/SwagMigrationFixDefinition.php new file mode 100644 index 000000000..d0f2ff340 --- /dev/null +++ b/src/Migration/ErrorResolution/Entity/SwagMigrationFixDefinition.php @@ -0,0 +1,54 @@ + + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace SwagMigrationAssistant\Migration\ErrorResolution\Entity; + +use Shopware\Core\Framework\DataAbstractionLayer\EntityDefinition; +use Shopware\Core\Framework\DataAbstractionLayer\Field\CreatedAtField; +use Shopware\Core\Framework\DataAbstractionLayer\Field\Flag\PrimaryKey; +use Shopware\Core\Framework\DataAbstractionLayer\Field\Flag\Required; +use Shopware\Core\Framework\DataAbstractionLayer\Field\IdField; +use Shopware\Core\Framework\DataAbstractionLayer\Field\StringField; +use Shopware\Core\Framework\DataAbstractionLayer\Field\UpdatedAtField; +use Shopware\Core\Framework\DataAbstractionLayer\FieldCollection; +use Shopware\Core\Framework\Log\Package; +use SwagMigrationAssistant\Core\Field\AnyJsonField; + +#[Package('fundamentals@after-sales')] +class SwagMigrationFixDefinition extends EntityDefinition +{ + public const ENTITY_NAME = 'swag_migration_fix'; + + public function getEntityName(): string + { + return self::ENTITY_NAME; + } + + public function getCollectionClass(): string + { + return SwagMigrationFixCollection::class; + } + + public function getEntityClass(): string + { + return SwagMigrationFixEntity::class; + } + + protected function defineFields(): FieldCollection + { + return new FieldCollection([ + (new IdField('id', 'id'))->addFlags(new PrimaryKey(), new Required()), + (new IdField('connection_id', 'connectionId'))->addFlags(new Required()), + (new AnyJsonField('value', 'value'))->addFlags(new Required()), + (new StringField('path', 'path'))->addFlags(new Required()), + new IdField('entity_id', 'entityId'), + new StringField('entity_name', 'entityName'), + new CreatedAtField(), + new UpdatedAtField(), + ]); + } +} diff --git a/src/Migration/ErrorResolution/Entity/SwagMigrationFixEntity.php b/src/Migration/ErrorResolution/Entity/SwagMigrationFixEntity.php new file mode 100644 index 000000000..71b3e991c --- /dev/null +++ b/src/Migration/ErrorResolution/Entity/SwagMigrationFixEntity.php @@ -0,0 +1,78 @@ + + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace SwagMigrationAssistant\Migration\ErrorResolution\Entity; + +use Shopware\Core\Framework\DataAbstractionLayer\Entity; +use Shopware\Core\Framework\DataAbstractionLayer\EntityIdTrait; +use Shopware\Core\Framework\Log\Package; + +#[Package('fundamentals@after-sales')] +class SwagMigrationFixEntity extends Entity +{ + use EntityIdTrait; + + protected string $connectionId; + + protected mixed $value; + + protected string $path; + + protected string $entityId; + + protected string $entityName; + + public function getConnectionId(): string + { + return $this->connectionId; + } + + public function setConnectionId(string $connectionId): void + { + $this->connectionId = $connectionId; + } + + public function getValue(): mixed + { + return $this->value; + } + + public function setValue(mixed $value): void + { + $this->value = $value; + } + + public function getPath(): string + { + return $this->path; + } + + public function setPath(string $path): void + { + $this->path = $path; + } + + public function getEntityId(): string + { + return $this->entityId; + } + + public function setEntityId(string $entityId): void + { + $this->entityId = $entityId; + } + + public function getEntityName(): string + { + return $this->entityName; + } + + public function setEntityName(string $entityName): void + { + $this->entityName = $entityName; + } +} diff --git a/src/Migration/ErrorResolution/Event/MigrationPostErrorResolutionEvent.php b/src/Migration/ErrorResolution/Event/MigrationPostErrorResolutionEvent.php new file mode 100644 index 000000000..625b9f2df --- /dev/null +++ b/src/Migration/ErrorResolution/Event/MigrationPostErrorResolutionEvent.php @@ -0,0 +1,40 @@ + + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace SwagMigrationAssistant\Migration\ErrorResolution\Event; + +use Shopware\Core\Framework\Context; +use Shopware\Core\Framework\Event\ShopwareEvent; +use Shopware\Core\Framework\Log\Package; +use SwagMigrationAssistant\Migration\ErrorResolution\MigrationErrorResolutionContext; +use Symfony\Contracts\EventDispatcher\Event; + +/** + * @final + * + * @codeCoverageIgnore + */ +#[Package('fundamentals@after-sales')] +class MigrationPostErrorResolutionEvent extends Event implements ShopwareEvent +{ + /** + * @internal + */ + public function __construct(private readonly MigrationErrorResolutionContext $errorResolutionContext) + { + } + + public function getErrorResolutionContext(): MigrationErrorResolutionContext + { + return $this->errorResolutionContext; + } + + public function getContext(): Context + { + return $this->errorResolutionContext->getContext(); + } +} diff --git a/src/Migration/ErrorResolution/Event/MigrationPreErrorResolutionEvent.php b/src/Migration/ErrorResolution/Event/MigrationPreErrorResolutionEvent.php new file mode 100644 index 000000000..fa028df49 --- /dev/null +++ b/src/Migration/ErrorResolution/Event/MigrationPreErrorResolutionEvent.php @@ -0,0 +1,40 @@ + + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace SwagMigrationAssistant\Migration\ErrorResolution\Event; + +use Shopware\Core\Framework\Context; +use Shopware\Core\Framework\Event\ShopwareEvent; +use Shopware\Core\Framework\Log\Package; +use SwagMigrationAssistant\Migration\ErrorResolution\MigrationErrorResolutionContext; +use Symfony\Contracts\EventDispatcher\Event; + +/** + * @final + * + * @codeCoverageIgnore + */ +#[Package('fundamentals@after-sales')] +class MigrationPreErrorResolutionEvent extends Event implements ShopwareEvent +{ + /** + * @internal + */ + public function __construct(private readonly MigrationErrorResolutionContext $errorResolutionContext) + { + } + + public function getErrorResolutionContext(): MigrationErrorResolutionContext + { + return $this->errorResolutionContext; + } + + public function getContext(): Context + { + return $this->errorResolutionContext->getContext(); + } +} diff --git a/src/Migration/ErrorResolution/MigrationErrorResolutionContext.php b/src/Migration/ErrorResolution/MigrationErrorResolutionContext.php new file mode 100644 index 000000000..491ae39df --- /dev/null +++ b/src/Migration/ErrorResolution/MigrationErrorResolutionContext.php @@ -0,0 +1,82 @@ + + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace SwagMigrationAssistant\Migration\ErrorResolution; + +use Shopware\Core\Framework\Context; +use Shopware\Core\Framework\Log\Package; + +/** + * @final + * + * @codeCoverageIgnore + */ +#[Package('fundamentals@after-sales')] +class MigrationErrorResolutionContext +{ + /** + * @internal + * + * @param array> $data + * @param array> $fixes + */ + public function __construct( + private array &$data, + private array &$fixes, + private readonly string $connectionId, + private readonly string $runId, + private readonly Context $context, + ) { + } + + /** + * @return array> + */ + public function getData(): array + { + return $this->data; + } + + /** + * @param array> $data + */ + public function setData(array $data): void + { + $this->data = $data; + } + + /** + * @return array> + */ + public function getFixes(): array + { + return $this->fixes; + } + + /** + * @param array> $fixes + */ + public function setFixes(array $fixes): void + { + $this->fixes = $fixes; + } + + public function getConnectionId(): string + { + return $this->connectionId; + } + + public function getRunId(): string + { + return $this->runId; + } + + public function getContext(): Context + { + return $this->context; + } +} diff --git a/src/Migration/ErrorResolution/MigrationErrorResolutionService.php b/src/Migration/ErrorResolution/MigrationErrorResolutionService.php new file mode 100644 index 000000000..206ac330a --- /dev/null +++ b/src/Migration/ErrorResolution/MigrationErrorResolutionService.php @@ -0,0 +1,126 @@ + + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace SwagMigrationAssistant\Migration\ErrorResolution; + +use Doctrine\DBAL\ArrayParameterType; +use Doctrine\DBAL\Connection; +use Shopware\Core\Framework\Context; +use Shopware\Core\Framework\Log\Package; +use Shopware\Core\Framework\Uuid\Uuid; +use SwagMigrationAssistant\Migration\ErrorResolution\Event\MigrationPostErrorResolutionEvent; +use SwagMigrationAssistant\Migration\ErrorResolution\Event\MigrationPreErrorResolutionEvent; +use Symfony\Contracts\EventDispatcher\EventDispatcherInterface; + +/** + * @internal + */ +#[Package('fundamentals@after-sales')] +readonly class MigrationErrorResolutionService +{ + public function __construct( + private Connection $connection, + private EventDispatcherInterface $eventDispatcher, + ) { + } + + /** + * @param array> $data + */ + public function applyFixes(array &$data, string $connectionId, string $runId, Context $context): void + { + $emptyFixes = []; + $errorResolutionContext = new MigrationErrorResolutionContext( + $data, + $emptyFixes, + $connectionId, + $runId, + $context, + ); + + $this->loadFixes($errorResolutionContext); + + $this->eventDispatcher->dispatch( + new MigrationPreErrorResolutionEvent($errorResolutionContext), + ); + + $fixes = $errorResolutionContext->getFixes(); + $data = $errorResolutionContext->getData(); + + foreach ($data as &$item) { + $id = $item['id']; + + if (!\array_key_exists($id, $fixes) || !\is_array($fixes[$id])) { + continue; + } + + foreach ($fixes[$id] as $fix) { + $fix->apply($item); + } + } + + unset($item); + + $errorResolutionContext->setData($data); + + $this->eventDispatcher->dispatch( + new MigrationPostErrorResolutionEvent($errorResolutionContext), + ); + + $data = $errorResolutionContext->getData(); + } + + /** + * Loads fixes from the database and populates them in the context. + */ + private function loadFixes(MigrationErrorResolutionContext $errorResolutionContext): void + { + $itemIds = \array_column($errorResolutionContext->getData(), 'id'); + + if (empty($itemIds)) { + $errorResolutionContext->setFixes([]); + + return; + } + + // To ensure, only select fixes for the current run, join swag_migration_logging table and filter by run_id + $sql = <<<'SQL' +SELECT fix.entity_id AS entityId, fix.id, fix.value, fix.path +FROM swag_migration_fix AS fix +INNER JOIN swag_migration_logging AS log ON log.entity_id = fix.entity_id +WHERE fix.entity_id IN (:ids) +AND fix.connection_id = :connectionId +AND log.run_id = :runId +AND log.user_fixable = 1; +SQL; + + $result = $this->connection->fetchAllAssociative( + $sql, + [ + 'ids' => Uuid::fromHexToBytesList($itemIds), + 'connectionId' => Uuid::fromHexToBytes($errorResolutionContext->getConnectionId()), + 'runId' => Uuid::fromHexToBytes($errorResolutionContext->getRunId()), + ], + [ + 'ids' => ArrayParameterType::STRING, + ] + ); + + $fixes = []; + foreach ($result as $row) { + $entityId = Uuid::fromBytesToHex($row['entityId']); + + if (!\array_key_exists($entityId, $fixes)) { + $fixes[$entityId] = []; + } + + $fixes[$entityId][] = MigrationFix::fromDatabaseQuery($row); + } + + $errorResolutionContext->setFixes($fixes); + } +} diff --git a/src/Migration/ErrorResolution/MigrationFix.php b/src/Migration/ErrorResolution/MigrationFix.php new file mode 100644 index 000000000..80530c08f --- /dev/null +++ b/src/Migration/ErrorResolution/MigrationFix.php @@ -0,0 +1,87 @@ + + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace SwagMigrationAssistant\Migration\ErrorResolution; + +use Shopware\Core\Framework\Log\Package; +use Shopware\Core\Framework\Uuid\Uuid; +use SwagMigrationAssistant\Exception\MigrationException; + +/** + * @final + */ +#[Package('fundamentals@after-sales')] +readonly class MigrationFix +{ + private const PATH_SEPARATOR = '.'; + + public function __construct( + public string $id, + public string $value, + public string $path, + ) { + } + + /** + * @param array $data + */ + public static function fromDatabaseQuery(array $data): self + { + $expectedArrayKeys = ['id', 'value', 'path']; + foreach ($expectedArrayKeys as $expectedKey) { + if (!\array_key_exists($expectedKey, $data)) { + throw MigrationException::couldNotConvertFix($expectedKey); + } + } + + return new self( + Uuid::fromBytesToHex($data['id']), + $data['value'], + $data['path'], + ); + } + + /** + * @param array $item + */ + public function apply(array &$item): void + { + /* + * Explode the path to an array + * Path example: 'category.language.name' + * Results in an array like: ['category', 'language', 'name'] + */ + $pathArray = explode(self::PATH_SEPARATOR, $this->path); + + /* + * Set current item as pointer + * Item structure for example has no valid value for name and looks like: + * [ + * 'someOtherKeys', + * ... + * category => [ + * ... + * 'language' => [ + * ... + * 'name' => null, + * ] + * ] + * ] + */ + $nestedPointer = &$item; + + // Iterating over the path to follow them and set the nested pointer to the last key in pathArray + // In this example the result pointer is: $item['category']['language']['name'] + foreach ($pathArray as $key) { + $nestedPointer = &$nestedPointer[$key]; + } + + // Now set the value to the pointer like: $item['category']['language']['name'] = 'new Value' + $nestedPointer = \json_decode($this->value, true, 512, \JSON_THROW_ON_ERROR); + unset($nestedPointer); + } +} diff --git a/src/Migration/Gateway/GatewayInterface.php b/src/Migration/Gateway/GatewayInterface.php index ff489dd40..f875cb65f 100644 --- a/src/Migration/Gateway/GatewayInterface.php +++ b/src/Migration/Gateway/GatewayInterface.php @@ -11,6 +11,7 @@ use Shopware\Core\Framework\Log\Package; use SwagMigrationAssistant\Migration\EnvironmentInformation; use SwagMigrationAssistant\Migration\MigrationContextInterface; +use SwagMigrationAssistant\Migration\Profile\ProfileInterface; use SwagMigrationAssistant\Migration\TotalStruct; #[Package('fundamentals@after-sales')] @@ -23,7 +24,7 @@ public function getSnippetName(): string; /** * Identifier for a gateway registry */ - public function supports(MigrationContextInterface $migrationContext): bool; + public function supports(ProfileInterface $profile): bool; /** * Reads the given entity type from via context from its connection and returns the data diff --git a/src/Migration/Gateway/GatewayRegistry.php b/src/Migration/Gateway/GatewayRegistry.php index 7ba39d663..564ad34c6 100644 --- a/src/Migration/Gateway/GatewayRegistry.php +++ b/src/Migration/Gateway/GatewayRegistry.php @@ -26,9 +26,11 @@ public function __construct(private readonly iterable $gateways) */ public function getGateways(MigrationContextInterface $migrationContext): array { + $profile = $migrationContext->getProfile(); + $gateways = []; foreach ($this->gateways as $gateway) { - if ($gateway->supports($migrationContext)) { + if ($gateway->supports($profile)) { $gateways[] = $gateway; } } @@ -39,15 +41,11 @@ public function getGateways(MigrationContextInterface $migrationContext): array public function getGateway(MigrationContextInterface $migrationContext): GatewayInterface { $connection = $migrationContext->getConnection(); - if ($connection === null) { - throw MigrationException::migrationContextPropertyMissing('Connection'); - } - $profileName = $connection->getProfileName(); $gatewayName = $connection->getGatewayName(); foreach ($this->gateways as $gateway) { - if ($gateway->supports($migrationContext) && $gateway->getName() === $gatewayName) { + if ($gateway->supports($migrationContext->getProfile()) && $gateway->getName() === $gatewayName) { return $gateway; } } diff --git a/src/Migration/History/HistoryService.php b/src/Migration/History/HistoryService.php index 573d36542..587c9d8cb 100644 --- a/src/Migration/History/HistoryService.php +++ b/src/Migration/History/HistoryService.php @@ -31,8 +31,8 @@ #[Package('fundamentals@after-sales')] class HistoryService implements HistoryServiceInterface { - private const LOG_FETCH_LIMIT = 50; - private const LOG_TIME_FORMAT = 'd.m.Y h:i:s e'; + public const LOG_FETCH_LIMIT = 50; + public const LOG_TIME_FORMAT = 'Y-m-d H:i:s T'; /** * @param EntityRepository $runRepo @@ -59,25 +59,14 @@ public function getGroupedLogsOfRun( null, null, new TermsAggregation( - 'titleSnippet', - 'titleSnippet', - null, - null, - new TermsAggregation( - 'entity', - 'entity', - null, - null, - new TermsAggregation( - 'level', - 'level' - ) - ) + 'level', + 'level' ) ) ); $result = $this->loggingRepo->aggregate($criteria, $context); + /** @var TermsResult $termsResult */ $termsResult = $result->get('count'); $aggregateResult = $termsResult->getBuckets(); @@ -87,6 +76,7 @@ public function getGroupedLogsOfRun( } $cleanResult = []; + foreach ($aggregateResult as $bucket) { $detailInformation = $this->extractBucketInformation($bucket); $cleanResult[] = $detailInformation; @@ -100,30 +90,39 @@ public function getGroupedLogsOfRun( */ public function downloadLogsOfRun(string $runUuid, Context $context): \Closure { - $offset = 0; - $total = $this->getTotalLogCount($runUuid, $context); $run = $this->getMigrationRun($runUuid, $context); - return function () use ($run, $runUuid, $offset, $total, $context): void { - if ($run !== null) { - \printf('%s%s', $this->getPrefixLogInformation($run), \PHP_EOL); + if ($run === null) { + throw MigrationException::entityNotExists( + SwagMigrationRunEntity::class, + $runUuid + ); + } + + $total = $this->getTotalLogCount($runUuid, $context); + + return function () use ($run, $runUuid, $total, $context): void { + $offset = 0; + + \printf('%s', $this->getPrefixLogInformation($run)); + + if ($total === 0) { + \printf('%sNo log entries found for this migration run.%s', \PHP_EOL, \PHP_EOL); } while ($offset < $total) { $logChunk = $this->getLogChunk($runUuid, $offset, $context); foreach ($logChunk->getElements() as $logEntry) { - \printf('[%s] %s%s', $logEntry->getLevel(), $logEntry->getCode(), \PHP_EOL); - \printf('%s%s', $logEntry->getTitle(), \PHP_EOL); - \printf('%s%s%s', $logEntry->getDescription(), \PHP_EOL, \PHP_EOL); + if (!$logEntry instanceof SwagMigrationLoggingEntity) { + continue; + } + + $this->printLogEntry($logEntry); } $offset += self::LOG_FETCH_LIMIT; } - - if ($run !== null) { - \printf('%s%s%s', $this->getSuffixLogInformation($run), \PHP_EOL, \PHP_EOL); - } }; } @@ -136,7 +135,7 @@ public function clearDataOfRun(string $runUuid, Context $context): void } if ($run->getStep()->isRunning()) { - throw MigrationException::migrationIsAlreadyRunning(); + throw MigrationException::migrationProcessing(); } $this->connection->executeStatement('DELETE FROM swag_migration_logging WHERE run_id = :runId', ['runId' => Uuid::fromHexToBytes($runUuid)]); @@ -151,31 +150,67 @@ public function isMediaProcessing(): bool 'SELECT COUNT(id) FROM swag_migration_media_file WHERE processed = 0 and process_failure != 1' )->fetchOne(); - return $unprocessedCount !== '0'; + return (int) $unprocessedCount !== 0; } - private function extractBucketInformation(Bucket $bucket): array + private function printLogEntry(SwagMigrationLoggingEntity $logEntry): void { - /** @var TermsResult $titleResult */ - $titleResult = $bucket->getResult(); - $titleBucket = $titleResult->getBuckets()[0]; + \printf('----- Log Entry #%d -----%s', $logEntry->getAutoIncrement(), \PHP_EOL); + \printf('ID: %s%s', $logEntry->getId(), \PHP_EOL); + \printf('Level: %s%s', $logEntry->getLevel(), \PHP_EOL); + \printf('Code: %s%s', $logEntry->getCode(), \PHP_EOL); + \printf('Profile name: %s%s', $logEntry->getProfileName(), \PHP_EOL); + \printf('Gateway name: %s%s', $logEntry->getGatewayName(), \PHP_EOL); + \printf('Created at: %s%s', $logEntry->getCreatedAt()?->format(self::LOG_TIME_FORMAT) ?? '-', \PHP_EOL); + + if ($logEntry->getEntityName()) { + \printf('Entity: %s%s', $logEntry->getEntityName(), \PHP_EOL); + } - /** @var TermsResult $entityResult */ - $entityResult = $titleBucket->getResult(); - $entityString = empty($entityResult->getBuckets()) ? '' : $entityResult->getBuckets()[0]->getKey(); + if ($logEntry->getFieldName()) { + \printf('Field: %s%s', $logEntry->getFieldName(), \PHP_EOL); + } + + if ($logEntry->getFieldSourcePath()) { + \printf('Source path: %s%s', $logEntry->getFieldSourcePath(), \PHP_EOL); + } + + if ($logEntry->getExceptionMessage()) { + \printf('Exception message: %s%s', $logEntry->getExceptionMessage(), \PHP_EOL); + } + + if ($logEntry->getSourceData()) { + \printf('Source data (JSON):%s%s%s', \PHP_EOL, \json_encode($logEntry->getSourceData(), \JSON_PRETTY_PRINT) ?: '{}', \PHP_EOL); + } + if ($logEntry->getConvertedData()) { + \printf('Converted data (JSON):%s%s%s', \PHP_EOL, \json_encode($logEntry->getConvertedData(), \JSON_PRETTY_PRINT) ?: '{}', \PHP_EOL); + } + + if ($logEntry->getExceptionTrace()) { + \printf('Exception trace (JSON):%s%s%s', \PHP_EOL, \json_encode($logEntry->getExceptionTrace(), \JSON_PRETTY_PRINT) ?: '{}', \PHP_EOL); + } + + \printf(\PHP_EOL); + } + + private function extractBucketInformation(Bucket $bucket): array + { + /** @var TermsResult|null $levelResult */ + $levelResult = $bucket->getResult(); $levelString = ''; - if ($entityString !== '') { - /** @var TermsResult $levelResult */ - $levelResult = $entityResult->getBuckets()[0]->getResult(); - $levelString = empty($levelResult->getBuckets()) ? '' : $levelResult->getBuckets()[0]->getKey(); + + if ($levelResult !== null) { + $levelBuckets = $levelResult->getBuckets(); + + if (!empty($levelBuckets)) { + $levelString = $levelBuckets[0]->getKey(); + } } return [ 'code' => $bucket->getKey(), 'count' => $bucket->getCount(), - 'titleSnippet' => $titleBucket->getKey(), - 'entity' => $entityString, 'level' => $levelString, ]; } @@ -187,6 +222,7 @@ private function getTotalLogCount(string $runUuid, Context $context): int $criteria->addAggregation(new CountAggregation('count', 'id')); $result = $this->loggingRepo->aggregate($criteria, $context); + /** @var CountResult $countResult */ $countResult = $result->get('count'); @@ -208,6 +244,7 @@ private function getLogChunk(string $runUuid, int $offset, Context $context): En { $criteria = new Criteria(); $criteria->addFilter(new EqualsFilter('runId', $runUuid)); + $criteria->addFilter(new EqualsFilter('userFixable', 0)); $criteria->addSorting(new FieldSorting('autoIncrement', FieldSorting::ASCENDING)); $criteria->setOffset($offset); $criteria->setLimit(self::LOG_FETCH_LIMIT); @@ -221,38 +258,38 @@ private function getPrefixLogInformation(SwagMigrationRunEntity $run): string $profileName = '-'; $gatewayName = '-'; $connectionName = '-'; + + $premapping = 'Associated connection not found'; + if ($connection !== null) { $connectionName = $connection->getName(); $profileName = $connection->getProfileName(); $gatewayName = $connection->getGatewayName(); + $premapping = $connection->getPremapping(); } - $updatedAt = $run->getUpdatedAt(); - if ($updatedAt !== null) { - $updatedAt = $updatedAt->format(self::LOG_TIME_FORMAT); - } else { - $updatedAt = '-'; - } - - $createdAt = $run->getCreatedAt(); - if ($createdAt !== null) { - $createdAt = $createdAt->format(self::LOG_TIME_FORMAT); - } else { - $createdAt = '-'; - } + $updatedAt = $run->getUpdatedAt()?->format(self::LOG_TIME_FORMAT) ?? '-'; + $createdAt = $run->getCreatedAt()?->format(self::LOG_TIME_FORMAT) ?? '-'; return \sprintf( - 'Migration log generated at %s' . \PHP_EOL - . 'Run id: %s' . \PHP_EOL + '########## MIGRATION LOG ##########' . \PHP_EOL . \PHP_EOL + . '########## RUN INFORMATION ##########' . \PHP_EOL + . 'Generated at: %s' . \PHP_EOL + . 'Run ID: %s' . \PHP_EOL . 'Status: %s' . \PHP_EOL . 'Created at: %s' . \PHP_EOL - . 'Updated at: %s' . \PHP_EOL - . 'Connection id: %s' . \PHP_EOL + . 'Updated at: %s' . \PHP_EOL . \PHP_EOL + . '########## CONNECTION INFORMATION ##########' . \PHP_EOL + . 'Connection ID: %s' . \PHP_EOL . 'Connection name: %s' . \PHP_EOL - . 'Profile: %s' . \PHP_EOL - . 'Gateway: %s' . \PHP_EOL . \PHP_EOL - . 'Selected dataSets:' . \PHP_EOL . '%s' . \PHP_EOL - . '--------------------Log-entries---------------------' . \PHP_EOL, + . 'Profile name: %s' . \PHP_EOL + . 'Gateway name: %s' . \PHP_EOL . \PHP_EOL + . '########## SELECTED DATASETS ##########' . \PHP_EOL + . '%s' . \PHP_EOL + . '########## ADDITIONAL METADATA ##########' . \PHP_EOL + . 'Environment information (JSON):' . \PHP_EOL . '%s' . \PHP_EOL . \PHP_EOL + . 'Pre-mapping (JSON):' . \PHP_EOL . '%s' . \PHP_EOL . \PHP_EOL + . '########## LOG ENTRIES ##########' . \PHP_EOL, \date(self::LOG_TIME_FORMAT), $run->getId(), $run->getStepValue(), @@ -262,38 +299,24 @@ private function getPrefixLogInformation(SwagMigrationRunEntity $run): string $connectionName, $profileName, $gatewayName, - $this->getFormattedSelectedDataSets($run->getProgress()) + $this->getFormattedSelectedDataSets($run->getProgress()), + \json_encode($run->getEnvironmentInformation(), \JSON_PRETTY_PRINT), + \json_encode($premapping, \JSON_PRETTY_PRINT) ); } private function getFormattedSelectedDataSets(?MigrationProgress $progress): string { if ($progress === null || $progress->getDataSets()->count() < 1) { - return ''; + return 'No datasets selected.' . \PHP_EOL; } $output = ''; + foreach ($progress->getDataSets() as $dataSet) { - $output .= \sprintf('- %s (total: %d)' . \PHP_EOL, $dataSet->getEntityName(), $dataSet->getTotal()); + $output .= \sprintf('- %s (Total: %d)' . \PHP_EOL, $dataSet->getEntityName(), $dataSet->getTotal()); } return $output; } - - private function getSuffixLogInformation(SwagMigrationRunEntity $run): string - { - $connection = $run->getConnection(); - $premapping = 'Associated connection not found'; - if ($connection !== null) { - $premapping = $connection->getPremapping(); - } - - return \sprintf( - '--------------------Additional-metadata---------------------' . \PHP_EOL - . 'Environment information {JSON}:' . \PHP_EOL . '%s' . \PHP_EOL . \PHP_EOL - . 'Premapping {JSON}: ----------------------------------------------------' . \PHP_EOL . '%s' . \PHP_EOL, - \json_encode($run->getEnvironmentInformation(), \JSON_PRETTY_PRINT), - \json_encode($premapping, \JSON_PRETTY_PRINT) - ); - } } diff --git a/src/Migration/History/LogGroupingService.php b/src/Migration/History/LogGroupingService.php new file mode 100644 index 000000000..3ffd221df --- /dev/null +++ b/src/Migration/History/LogGroupingService.php @@ -0,0 +1,440 @@ + + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace SwagMigrationAssistant\Migration\History; + +use Doctrine\DBAL\Connection; +use Doctrine\DBAL\Exception; +use Doctrine\DBAL\ParameterType; +use Shopware\Core\Framework\Log\Package; +use Shopware\Core\Framework\Uuid\Uuid; +use SwagMigrationAssistant\Exception\MigrationException; + +/** + * @internal + * + * @SECURITY-NOTICE + * + * This service builds dynamic SQL queries with string interpolation for performance reasons. + * While this looks dangerous, it is SAFE because: + * + * 1. All user-controllable values that get interpolated into SQL (sortBy, sortDirection, filterStatus) + * are validated against explicit allowlists BEFORE being used in query construction. + * See: ALLOWED_SORT_COLUMNS, ALLOWED_SORT_DIRECTIONS, ALLOWED_FILTER_STATUSES constants. + * + * 2. All data values (runId, connectionId, filterCode, filterEntity, filterField) are passed + * as bound parameters (:paramName), never interpolated into SQL strings. + * + * The validation is centralized at the top of getGroupedLogsByCodeAndEntity() to make + * security review straightforward. Do not scatter validation logic across multiple methods. + */ +#[Package('fundamentals@after-sales')] +readonly class LogGroupingService +{ + /** + * allowlist of columns that can be used for ORDER BY. + * keys are API parameter names, values are actual SQL column references. + * + * @SECURITY only these exact values can be interpolated into ORDER BY clauses. + */ + private const ALLOWED_SORT_COLUMNS = [ + 'count' => 'count', + 'code' => 'l.code', + 'entityName' => 'l.entity_name', + 'fieldName' => 'l.field_name', + 'profileName' => 'l.profile_name', + 'gatewayName' => 'l.gateway_name', + ]; + + /** + * allowlist of valid sort directions. + * + * @SECURITY only these exact values can be interpolated into ORDER BY clauses. + */ + private const ALLOWED_SORT_DIRECTIONS = ['ASC', 'DESC']; + + /** + * allowlist of valid filter status values. + * + * @SECURITY only these exact values can trigger HAVING clause generation. + */ + private const ALLOWED_FILTER_STATUSES = ['resolved', 'unresolved']; + + public function __construct( + private Connection $connection, + ) { + } + + /** + * @throws Exception + * + * @return array{total: int, items: array, levelCounts: array{error: int, warning: int, info: int}} + */ + public function getGroupedLogsByCodeAndEntity( + string $runUuid, + string $level, + int $page, + int $limit, + string $sortBy, + string $sortDirection, + ?string $filterCode, + ?string $filterStatus, + ?string $filterEntity, + ?string $filterField, + ): array { + /** @SECURITY validates all values that will be interpolated into SQL - do not skip this step. */ + $orderColumn = $this->validateSortColumn($sortBy); + $orderDirection = $this->validateSortDirection($sortDirection); + $validatedFilterStatus = $this->validateFilterStatus($filterStatus); + + $runIdBytes = Uuid::fromHexToBytes($runUuid); + $connectionIdBytes = $this->getConnectionIdForRun($runIdBytes); + + $params = [ + 'runId' => $runIdBytes, + 'level' => $level, + 'limit' => $limit, + 'offset' => ($page - 1) * $limit, + 'connectionId' => $connectionIdBytes, + ]; + + // build optional WHERE conditions + $whereConditions = []; + + if ($filterCode !== null) { + $whereConditions[] = 'l.code = :filterCode'; + $params['filterCode'] = $filterCode; + } + + if ($filterEntity !== null) { + $whereConditions[] = 'l.entity_name = :filterEntity'; + $params['filterEntity'] = $filterEntity; + } + + if ($filterField !== null) { + $whereConditions[] = 'l.field_name = :filterField'; + $params['filterField'] = $filterField; + } + + $additionalWhere = $whereConditions !== [] ? ' AND ' . \implode(' AND ', $whereConditions) : ''; + + // determine if we need the fix join for status filtering + $includeFixJoin = $validatedFilterStatus !== null; + + $sql = $this->buildMainQuery( + $additionalWhere, + $validatedFilterStatus, + $orderColumn, + $orderDirection, + $includeFixJoin + ); + + $result = $this->connection->executeQuery($sql, $params, [ + 'limit' => ParameterType::INTEGER, + 'offset' => ParameterType::INTEGER, + ]); + + $rows = $result->fetchAllAssociative(); + $total = $rows !== [] ? (int) $rows[0]['total'] : 0; + + $levelCounts = $this->getLogLevelCounts( + $params, + $additionalWhere, + $validatedFilterStatus, + $includeFixJoin + ); + + return [ + 'total' => $total, + 'items' => $this->mapLogsFromRows($rows), + 'levelCounts' => $levelCounts, + ]; + } + + /** + * @throws Exception + * + * @return array + */ + public function getAllLogIdsByCodeAndEntity( + string $runId, + string $code, + string $entityName, + string $fieldName, + ?string $connectionId = null, + ): array { + $params = [ + 'runId' => Uuid::fromHexToBytes($runId), + 'code' => $code, + 'entityName' => $entityName, + 'fieldName' => $fieldName, + ]; + + // this is safe, it's a static string, not user input + $connectionJoinCondition = ''; + + if ($connectionId !== null && $connectionId !== '') { + $connectionJoinCondition = ' AND f.connection_id = :connectionId'; + $params['connectionId'] = Uuid::fromHexToBytes($connectionId); + } + + $sql = " + SELECT LOWER(HEX(l.id)) as id + FROM swag_migration_logging l + LEFT JOIN swag_migration_fix f ON ( + f.entity_name = l.entity_name + AND f.path = l.field_name + AND f.entity_id = l.entity_id + {$connectionJoinCondition} + ) + WHERE l.run_id = :runId + AND l.code = :code + AND l.entity_name = :entityName + AND l.field_name = :fieldName + AND l.user_fixable = 1 + AND f.id IS NULL + "; + + $result = $this->connection->executeQuery($sql, $params); + + return \array_column($result->fetchAllAssociative(), 'id'); + } + + /** + * validates sortBy parameter against allowlist and returns the SQL column name. + * returns 'count' as default if input is not in ALLOWED_SORT_COLUMNS. + */ + private function validateSortColumn(string $sortBy): string + { + return self::ALLOWED_SORT_COLUMNS[$sortBy] ?? 'count'; + } + + /** + * validates sortDirection parameter against allowlist. + * returns 'DESC' as default if input is not in ALLOWED_SORT_DIRECTIONS. + */ + private function validateSortDirection(string $sortDirection): string + { + $normalized = \strtoupper($sortDirection); + + return \in_array($normalized, self::ALLOWED_SORT_DIRECTIONS, true) ? $normalized : 'DESC'; + } + + /** + * validates filterStatus parameter against allowlist. + * returns null if input is not in ALLOWED_FILTER_STATUSES. + */ + private function validateFilterStatus(?string $filterStatus): ?string + { + if ($filterStatus === null) { + return null; + } + + return \in_array($filterStatus, self::ALLOWED_FILTER_STATUSES, true) ? $filterStatus : null; + } + + /** + * builds the main grouped logs query. + */ + private function buildMainQuery( + string $additionalWhere, + ?string $filterStatus, + string $orderColumn, + string $orderDirection, + bool $includeFixJoin, + ): string { + // build HAVING clause from validated filter status + $havingClause = match ($filterStatus) { + 'resolved' => 'HAVING COUNT(DISTINCT l.id) > 0 AND COUNT(DISTINCT l.id) = COUNT(DISTINCT f.id)', + 'unresolved' => 'HAVING COUNT(DISTINCT l.id) > 0 AND COUNT(DISTINCT l.id) != COUNT(DISTINCT f.id)', + default => '', + }; + + // build count subquery components + $countSubqueryFixJoin = $includeFixJoin + ? 'LEFT JOIN swag_migration_fix f2 ON ( + f2.connection_id = :connectionId + AND f2.entity_name = l2.entity_name + AND f2.path = l2.field_name + AND f2.entity_id = l2.entity_id + )' + : ''; + + $countSubqueryHaving = match ($filterStatus) { + 'resolved' => 'HAVING COUNT(DISTINCT l2.id) > 0 AND COUNT(DISTINCT l2.id) = COUNT(DISTINCT f2.id)', + 'unresolved' => 'HAVING COUNT(DISTINCT l2.id) > 0 AND COUNT(DISTINCT l2.id) != COUNT(DISTINCT f2.id)', + default => '', + }; + + $countSubqueryWhere = \str_replace('l.', 'l2.', $additionalWhere); + + /* + * MAIN QUERY STRUCTURE: + * this query groups logs by code, entity_name, and field_name, counting occurrences + * and tracking fix status. The subquery calculates total count for pagination. + */ + return " + SELECT + l.code, + l.entity_name, + l.field_name, + l.gateway_name, + l.profile_name, + COUNT(DISTINCT l.id) as count, + ( + SELECT COUNT(*) + FROM ( + SELECT 1 + FROM swag_migration_logging l2 + {$countSubqueryFixJoin} + WHERE l2.run_id = :runId + AND l2.level = :level + AND l2.user_fixable = 1 + {$countSubqueryWhere} + GROUP BY l2.code, l2.entity_name, l2.field_name + {$countSubqueryHaving} + ) as grouped_logs + ) as total, + COUNT(DISTINCT f.id) as fix_count + FROM swag_migration_logging l + LEFT JOIN swag_migration_fix f ON ( + f.connection_id = :connectionId + AND f.entity_name = l.entity_name + AND f.path = l.field_name + AND f.entity_id = l.entity_id + ) + WHERE l.run_id = :runId + AND l.level = :level + AND l.user_fixable = 1 + {$additionalWhere} + GROUP BY l.code, l.entity_name, l.field_name + {$havingClause} + ORDER BY {$orderColumn} {$orderDirection}, l.code ASC, l.entity_name ASC, l.field_name ASC + LIMIT :limit OFFSET :offset + "; + } + + /** + * gets log counts grouped by level for the filter badge counts. + * + * @param array $params + * + * @throws Exception + * + * @return array{error: int, warning: int, info: int} + */ + private function getLogLevelCounts( + array $params, + string $additionalWhere, + ?string $filterStatus, + bool $includeFixJoin, + ): array { + $joinClause = $includeFixJoin + ? 'LEFT JOIN swag_migration_fix f ON ( + f.connection_id = :connectionId + AND f.entity_name = l.entity_name + AND f.path = l.field_name + AND f.entity_id = l.entity_id + )' + : ''; + + $havingClause = $includeFixJoin + ? match ($filterStatus) { + 'resolved' => 'HAVING COUNT(DISTINCT l.id) > 0 AND COUNT(DISTINCT l.id) = COUNT(DISTINCT f.id)', + 'unresolved' => 'HAVING COUNT(DISTINCT l.id) > 0 AND COUNT(DISTINCT l.id) != COUNT(DISTINCT f.id)', + default => '', + } + : ''; + + $sql = " + SELECT + level, + COUNT(DISTINCT CONCAT(code, '|', COALESCE(entity_name, ''), '|', COALESCE(field_name, ''))) as count + FROM ( + SELECT + l.level, + l.code, + l.entity_name, + l.field_name + FROM swag_migration_logging l + {$joinClause} + WHERE l.run_id = :runId + AND l.user_fixable = 1 + {$additionalWhere} + GROUP BY l.level, l.code, l.entity_name, l.field_name + {$havingClause} + ) as filtered_logs + GROUP BY level + "; + + $result = $this->connection->executeQuery($sql, $params); + + return $this->mapLevelCountsFromRows($result->fetchAllAssociative()); + } + + /** + * @throws Exception + */ + private function getConnectionIdForRun(string $runIdBytes): string + { + $result = $this->connection->fetchOne( + 'SELECT connection_id FROM swag_migration_run WHERE id = :runId', + ['runId' => $runIdBytes] + ); + + if ($result === false) { + throw MigrationException::noConnectionFound(); + } + + return $result; + } + + /** + * @param array> $rows + * + * @return array + */ + private function mapLogsFromRows(array $rows): array + { + return \array_map( + static fn (array $row) => [ + 'code' => $row['code'], + 'entityName' => $row['entity_name'], + 'fieldName' => $row['field_name'], + 'profileName' => $row['profile_name'], + 'gatewayName' => $row['gateway_name'], + 'count' => (int) $row['count'], + 'fixCount' => (int) $row['fix_count'], + ], + $rows + ); + } + + /** + * @param array> $rows + * + * @return array{error: int, warning: int, info: int} + */ + private function mapLevelCountsFromRows(array $rows): array + { + $counts = [ + 'error' => 0, + 'warning' => 0, + 'info' => 0, + ]; + + foreach ($rows as $row) { + $level = \strtolower($row['level']); + + if (isset($counts[$level])) { + $counts[$level] = (int) $row['count']; + } + } + + return $counts; + } +} diff --git a/src/Migration/Logging/Log/AssociationRequiredMissingLog.php b/src/Migration/Logging/Log/AssociationRequiredMissingLog.php index 6e9ade2ca..608c5961f 100644 --- a/src/Migration/Logging/Log/AssociationRequiredMissingLog.php +++ b/src/Migration/Logging/Log/AssociationRequiredMissingLog.php @@ -8,17 +8,14 @@ namespace SwagMigrationAssistant\Migration\Logging\Log; use Shopware\Core\Framework\Log\Package; +use SwagMigrationAssistant\Migration\Logging\Log\Builder\AbstractMigrationLogEntry; #[Package('fundamentals@after-sales')] -class AssociationRequiredMissingLog extends BaseRunLogEntry +readonly class AssociationRequiredMissingLog extends AbstractMigrationLogEntry { - public function __construct( - string $runId, - string $entity, - string $sourceId, - private readonly string $requiredFor, - ) { - parent::__construct($runId, $entity, $sourceId); + public function isUserFixable(): bool + { + return false; } public function getLevel(): string @@ -28,55 +25,6 @@ public function getLevel(): string public function getCode(): string { - $entity = $this->getEntity(); - if ($entity === null) { - return 'SWAG_MIGRATION__SHOPWARE_ASSOCIATION_REQUIRED_MISSING'; - } - - return \sprintf('SWAG_MIGRATION__SHOPWARE_ASSOCIATION_REQUIRED_MISSING_%s', \mb_strtoupper($entity)); - } - - public function getTitle(): string - { - $entity = $this->getEntity(); - if ($entity === null) { - return 'Associated not found'; - } - - return \sprintf('Associated %s not found', $entity); - } - - /** - * @return array{missingEntity: ?string, requiredFor: string, sourceId: ?string} - */ - public function getParameters(): array - { - return [ - 'missingEntity' => $this->getEntity(), - 'requiredFor' => $this->requiredFor, - 'sourceId' => $this->getSourceId(), - ]; - } - - public function getDescription(): string - { - $args = $this->getParameters(); - - return \sprintf( - 'The %s with the source id "%s" can not be found but is required for %s.', - $args['missingEntity'], - $args['sourceId'], - $args['requiredFor'] - ); - } - - public function getTitleSnippet(): string - { - return \sprintf('%s.%s.title', $this->getSnippetRoot(), 'SWAG_MIGRATION__SHOPWARE_ASSOCIATION_REQUIRED_MISSING'); - } - - public function getDescriptionSnippet(): string - { - return \sprintf('%s.%s.description', $this->getSnippetRoot(), 'SWAG_MIGRATION__SHOPWARE_ASSOCIATION_REQUIRED_MISSING'); + return 'SWAG_MIGRATION__SHOPWARE_ASSOCIATION_REQUIRED_MISSING'; } } diff --git a/src/Migration/Logging/Log/BaseRunLogEntry.php b/src/Migration/Logging/Log/BaseRunLogEntry.php deleted file mode 100644 index 0d22aa7c5..000000000 --- a/src/Migration/Logging/Log/BaseRunLogEntry.php +++ /dev/null @@ -1,51 +0,0 @@ - - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace SwagMigrationAssistant\Migration\Logging\Log; - -use Shopware\Core\Framework\Log\Package; - -#[Package('fundamentals@after-sales')] -abstract class BaseRunLogEntry implements LogEntryInterface -{ - public function __construct( - protected string $runId, - protected ?string $entity = null, - protected ?string $sourceId = null, - ) { - } - - public function getRunId(): ?string - { - return $this->runId; - } - - public function getEntity(): ?string - { - return $this->entity; - } - - public function getSourceId(): ?string - { - return $this->sourceId; - } - - public function getSnippetRoot(): string - { - return 'swag-migration.index.error'; - } - - public function getTitleSnippet(): string - { - return \sprintf('%s.%s.title', $this->getSnippetRoot(), $this->getCode()); - } - - public function getDescriptionSnippet(): string - { - return \sprintf('%s.%s.description', $this->getSnippetRoot(), $this->getCode()); - } -} diff --git a/src/Migration/Logging/Log/Builder/AbstractMigrationLogEntry.php b/src/Migration/Logging/Log/Builder/AbstractMigrationLogEntry.php new file mode 100644 index 000000000..c013a93bf --- /dev/null +++ b/src/Migration/Logging/Log/Builder/AbstractMigrationLogEntry.php @@ -0,0 +1,103 @@ + + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace SwagMigrationAssistant\Migration\Logging\Log\Builder; + +use Shopware\Core\Framework\Log\Package; + +#[Package('fundamentals@after-sales')] +abstract readonly class AbstractMigrationLogEntry implements MigrationLogEntry +{ + final public const LOG_LEVEL_INFO = 'info'; + final public const LOG_LEVEL_WARNING = 'warning'; + final public const LOG_LEVEL_ERROR = 'error'; + final public const LOG_LEVEL_DEBUG = 'debug'; + + /** + * @param array|null $sourceData + * @param array|null $convertedData + * @param array|null $exceptionTrace + */ + public function __construct( + protected string $runId, + protected string $profileName, + protected string $gatewayName, + protected ?string $entityId = null, + protected ?string $entityName = null, + protected ?string $fieldName = null, + protected ?string $fieldSourcePath = null, + protected ?array $sourceData = null, + protected ?array $convertedData = null, + protected ?string $exceptionMessage = null, + protected ?array $exceptionTrace = null, + ) { + } + + public function getRunId(): string + { + return $this->runId; + } + + public function getProfileName(): string + { + return $this->profileName; + } + + public function getGatewayName(): string + { + return $this->gatewayName; + } + + public function getEntityName(): ?string + { + return $this->entityName; + } + + public function getFieldName(): ?string + { + return $this->fieldName; + } + + public function getFieldSourcePath(): ?string + { + return $this->fieldSourcePath; + } + + /** + * @return array|null + */ + public function getSourceData(): ?array + { + return $this->sourceData; + } + + /** + * @return array|null + */ + public function getConvertedData(): ?array + { + return $this->convertedData; + } + + public function getExceptionMessage(): ?string + { + return $this->exceptionMessage; + } + + /** + * @return array|null + */ + public function getExceptionTrace(): ?array + { + return $this->exceptionTrace; + } + + public function getEntityId(): ?string + { + return $this->entityId; + } +} diff --git a/src/Migration/Logging/Log/Builder/MigrationLogBuilder.php b/src/Migration/Logging/Log/Builder/MigrationLogBuilder.php new file mode 100644 index 000000000..b54a0674e --- /dev/null +++ b/src/Migration/Logging/Log/Builder/MigrationLogBuilder.php @@ -0,0 +1,158 @@ + + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace SwagMigrationAssistant\Migration\Logging\Log\Builder; + +use Shopware\Core\Framework\Log\Package; +use Shopware\Core\Framework\Uuid\Uuid; +use SwagMigrationAssistant\Migration\MigrationContextInterface; + +/** + * @final + * + * @example + * $log = (new MigrationLogBuilder('runId', 'profileName', 'gatewayName')) + * ->withField('fieldName') + * ->withFieldSourcePath('sourcePath') + * ->build(MigrationLogEntry::class); + */ +#[Package('fundamentals@after-sales')] +class MigrationLogBuilder +{ + /** + * @param array|null $sourceData + * @param array|null $convertedData + * @param array|null $exceptionTrace + */ + public function __construct( + protected string $runId, + protected string $profileName, + protected string $gatewayName, + protected ?string $entityId = null, + protected ?string $entityName = null, + protected ?string $fieldName = null, + protected ?string $fieldSourcePath = null, + protected ?array $sourceData = null, + protected ?array $convertedData = null, + protected ?string $exceptionMessage = null, + protected ?array $exceptionTrace = null, + ) { + } + + public static function fromMigrationContext(MigrationContextInterface $migrationContext): self + { + return new self( + $migrationContext->getRunUuid(), + $migrationContext->getConnection()->getProfileName(), + $migrationContext->getConnection()->getGatewayName(), + ); + } + + public function withEntityName(string $entityName): self + { + $this->entityName = $entityName; + + return $this; + } + + public function withFieldName(string $field): self + { + $this->fieldName = $field; + + return $this; + } + + public function withFieldSourcePath(string $fieldSourcePath): self + { + $this->fieldSourcePath = $fieldSourcePath; + + return $this; + } + + public function withEntityId(?string $entityId): self + { + $this->entityId = $this->getRevisedId($entityId); + + return $this; + } + + /** + * @param array $sourceData + */ + public function withSourceData(array $sourceData): self + { + $this->sourceData = $sourceData; + + return $this; + } + + /** + * @param array $convertedData + */ + public function withConvertedData(array $convertedData): self + { + $this->convertedData = $convertedData; + + return $this; + } + + public function withExceptionMessage(string $exceptionMessage): self + { + $this->exceptionMessage = $exceptionMessage; + + return $this; + } + + /** + * @param array $exceptionTrace + */ + public function withExceptionTrace(array $exceptionTrace): self + { + $this->exceptionTrace = $exceptionTrace; + + return $this; + } + + /** + * @template T of AbstractMigrationLogEntry + * + * @param class-string $logClass + * + * @return T + */ + public function build(string $logClass): AbstractMigrationLogEntry + { + \assert(\class_exists($logClass) && \is_subclass_of($logClass, AbstractMigrationLogEntry::class)); + + return new $logClass( + $this->runId, + $this->profileName, + $this->gatewayName, + $this->entityId, + $this->entityName, + $this->fieldName, + $this->fieldSourcePath, + $this->sourceData, + $this->convertedData, + $this->exceptionMessage, + $this->exceptionTrace, + ); + } + + private function getRevisedId(?string $id): ?string + { + if ($id === null) { + return null; + } + + if (Uuid::isValid($id)) { + return $id; + } + + return null; + } +} diff --git a/src/Migration/Logging/Log/Builder/MigrationLogEntry.php b/src/Migration/Logging/Log/Builder/MigrationLogEntry.php new file mode 100644 index 000000000..38794af7e --- /dev/null +++ b/src/Migration/Logging/Log/Builder/MigrationLogEntry.php @@ -0,0 +1,51 @@ + + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace SwagMigrationAssistant\Migration\Logging\Log\Builder; + +use Shopware\Core\Framework\Log\Package; + +#[Package('fundamentals@after-sales')] +interface MigrationLogEntry +{ + public function getRunId(): string; + + public function getProfileName(): string; + + public function getGatewayName(): string; + + public function getLevel(): string; + + public function getCode(): string; + + public function isUserFixable(): bool; + + public function getEntityId(): ?string; + + public function getEntityName(): ?string; + + public function getFieldName(): ?string; + + public function getFieldSourcePath(): ?string; + + /** + * @return array|null + */ + public function getSourceData(): ?array; + + /** + * @return array|null + */ + public function getConvertedData(): ?array; + + public function getExceptionMessage(): ?string; + + /** + * @return array|null + */ + public function getExceptionTrace(): ?array; +} diff --git a/src/Migration/Logging/Log/CannotConvertChildEntity.php b/src/Migration/Logging/Log/CannotConvertChildEntity.php deleted file mode 100644 index f97224fb3..000000000 --- a/src/Migration/Logging/Log/CannotConvertChildEntity.php +++ /dev/null @@ -1,82 +0,0 @@ - - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace SwagMigrationAssistant\Migration\Logging\Log; - -use Shopware\Core\Framework\Log\Package; - -#[Package('fundamentals@after-sales')] -class CannotConvertChildEntity extends BaseRunLogEntry -{ - public function __construct( - string $runId, - string $entity, - private readonly string $parentEntity, - private readonly string $parentSourceId, - ) { - parent::__construct($runId, $entity, null); - } - - public function getLevel(): string - { - return self::LOG_LEVEL_WARNING; - } - - public function getCode(): string - { - $entity = $this->getEntity(); - if ($entity === null) { - return 'SWAG_MIGRATION_CANNOT_CONVERT_CHILD_ENTITY'; - } - - return \sprintf('SWAG_MIGRATION_CANNOT_CONVERT_CHILD_%s_ENTITY', \mb_strtoupper($entity)); - } - - public function getTitle(): string - { - $entity = $this->getEntity(); - if ($entity === null) { - return 'The child entity could not be converted'; - } - - return \sprintf('The %s child entity could not be converted', $entity); - } - - /** - * @return array{entity: ?string, parentEntity: string, parentSourceId: string} - */ - public function getParameters(): array - { - return [ - 'entity' => $this->getEntity(), - 'parentEntity' => $this->parentEntity, - 'parentSourceId' => $this->parentSourceId, - ]; - } - - public function getDescription(): string - { - $args = $this->getParameters(); - - return \sprintf( - 'The %s child entity from the %s parent entity with the id "%s" could not be converted.', - $args['entity'], - $args['parentEntity'], - $args['parentSourceId'] - ); - } - - public function getTitleSnippet(): string - { - return \sprintf('%s.%s.title', $this->getSnippetRoot(), 'SWAG_MIGRATION_CANNOT_CONVERT_CHILD_ENTITY'); - } - - public function getDescriptionSnippet(): string - { - return \sprintf('%s.%s.description', $this->getSnippetRoot(), 'SWAG_MIGRATION_CANNOT_CONVERT_CHILD_ENTITY'); - } -} diff --git a/src/Migration/Logging/Log/CannotConvertChildEntityLog.php b/src/Migration/Logging/Log/CannotConvertChildEntityLog.php new file mode 100644 index 000000000..c97f8a621 --- /dev/null +++ b/src/Migration/Logging/Log/CannotConvertChildEntityLog.php @@ -0,0 +1,30 @@ + + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace SwagMigrationAssistant\Migration\Logging\Log; + +use Shopware\Core\Framework\Log\Package; +use SwagMigrationAssistant\Migration\Logging\Log\Builder\AbstractMigrationLogEntry; + +#[Package('fundamentals@after-sales')] +readonly class CannotConvertChildEntityLog extends AbstractMigrationLogEntry +{ + public function isUserFixable(): bool + { + return false; + } + + public function getLevel(): string + { + return self::LOG_LEVEL_WARNING; + } + + public function getCode(): string + { + return 'SWAG_MIGRATION_CANNOT_CONVERT_CHILD_ENTITY'; + } +} diff --git a/src/Migration/Logging/Log/CannotConvertEntity.php b/src/Migration/Logging/Log/CannotConvertEntity.php deleted file mode 100644 index 12588ae3d..000000000 --- a/src/Migration/Logging/Log/CannotConvertEntity.php +++ /dev/null @@ -1,79 +0,0 @@ - - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace SwagMigrationAssistant\Migration\Logging\Log; - -use Shopware\Core\Framework\Log\Package; - -#[Package('fundamentals@after-sales')] -class CannotConvertEntity extends BaseRunLogEntry -{ - public function __construct( - string $runId, - string $entity, - string $sourceId, - ) { - parent::__construct($runId, $entity, $sourceId); - } - - public function getLevel(): string - { - return self::LOG_LEVEL_WARNING; - } - - public function getCode(): string - { - $entity = $this->getEntity(); - if ($entity === null) { - return 'SWAG_MIGRATION_CANNOT_CONVERT'; - } - - return \sprintf('SWAG_MIGRATION_CANNOT_CONVERT_%s', \mb_strtoupper($entity)); - } - - public function getTitle(): string - { - $entity = $this->getEntity(); - if ($entity === null) { - return 'The entity could not be converted'; - } - - return \sprintf('The %s entity could not be converted', $entity); - } - - /** - * @return array{entity: ?string, sourceId: ?string} - */ - public function getParameters(): array - { - return [ - 'entity' => $this->getEntity(), - 'sourceId' => $this->getSourceId(), - ]; - } - - public function getDescription(): string - { - $args = $this->getParameters(); - - return \sprintf( - 'The %s entity with the source id "%s" could not be converted.', - $args['entity'], - $args['sourceId'] ?? 'null' - ); - } - - public function getTitleSnippet(): string - { - return \sprintf('%s.%s.title', $this->getSnippetRoot(), 'SWAG_MIGRATION_CANNOT_CONVERT_ENTITY'); - } - - public function getDescriptionSnippet(): string - { - return \sprintf('%s.%s.description', $this->getSnippetRoot(), 'SWAG_MIGRATION_CANNOT_CONVERT_ENTITY'); - } -} diff --git a/src/Migration/Logging/Log/CannotConvertEntityLog.php b/src/Migration/Logging/Log/CannotConvertEntityLog.php new file mode 100644 index 000000000..59b335aad --- /dev/null +++ b/src/Migration/Logging/Log/CannotConvertEntityLog.php @@ -0,0 +1,30 @@ + + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace SwagMigrationAssistant\Migration\Logging\Log; + +use Shopware\Core\Framework\Log\Package; +use SwagMigrationAssistant\Migration\Logging\Log\Builder\AbstractMigrationLogEntry; + +#[Package('fundamentals@after-sales')] +readonly class CannotConvertEntityLog extends AbstractMigrationLogEntry +{ + public function isUserFixable(): bool + { + return false; + } + + public function getLevel(): string + { + return self::LOG_LEVEL_WARNING; + } + + public function getCode(): string + { + return 'SWAG_MIGRATION_CANNOT_CONVERT'; + } +} diff --git a/src/Migration/Logging/Log/CannotGetFileRunLog.php b/src/Migration/Logging/Log/CannotGetFileRunLog.php index 56397ae6e..06fc4a512 100644 --- a/src/Migration/Logging/Log/CannotGetFileRunLog.php +++ b/src/Migration/Logging/Log/CannotGetFileRunLog.php @@ -7,20 +7,15 @@ namespace SwagMigrationAssistant\Migration\Logging\Log; -use GuzzleHttp\Exception\RequestException; use Shopware\Core\Framework\Log\Package; +use SwagMigrationAssistant\Migration\Logging\Log\Builder\AbstractMigrationLogEntry; #[Package('fundamentals@after-sales')] -class CannotGetFileRunLog extends BaseRunLogEntry +readonly class CannotGetFileRunLog extends AbstractMigrationLogEntry { - public function __construct( - string $runId, - string $entity, - string $sourceId, - private readonly string $uri, - private readonly ?RequestException $requestException = null, - ) { - parent::__construct($runId, $entity, $sourceId); + public function isUserFixable(): bool + { + return false; } public function getLevel(): string @@ -30,64 +25,6 @@ public function getLevel(): string public function getCode(): string { - $entity = $this->getEntity(); - if ($entity === null) { - return 'SWAG_MIGRATION_CANNOT_GET_FILE'; - } - - return \sprintf('SWAG_MIGRATION_CANNOT_GET_%s_FILE', \mb_strtoupper($entity)); - } - - public function getTitle(): string - { - $entity = $this->getEntity(); - if ($entity === null) { - return 'The file cannot be downloaded / copied'; - } - - return \sprintf('The %s file cannot be downloaded / copied', $entity); - } - - /** - * @return array{entity: ?string, sourceId: ?string, uri: string} - */ - public function getParameters(): array - { - return [ - 'entity' => $this->getEntity(), - 'sourceId' => $this->getSourceId(), - 'uri' => $this->uri, - ]; - } - - public function getDescription(): string - { - $args = $this->getParameters(); - - $description = \sprintf( - 'The %s file with the uri "%s" and media id "%s" cannot be downloaded / copied.', - $args['entity'], - $args['uri'], - $args['sourceId'] - ); - - if ($this->requestException !== null) { - $description .= \sprintf( - ' The following request error occurred: %s', - $this->requestException->getMessage() - ); - } - - return $description; - } - - public function getTitleSnippet(): string - { - return \sprintf('%s.%s.title', $this->getSnippetRoot(), 'SWAG_MIGRATION_CANNOT_GET_FILE'); - } - - public function getDescriptionSnippet(): string - { - return \sprintf('%s.%s.description', $this->getSnippetRoot(), 'SWAG_MIGRATION_CANNOT_GET_FILE'); + return 'SWAG_MIGRATION_CANNOT_GET_FILE'; } } diff --git a/src/Migration/Logging/Log/CannotReadEntityCountLog.php b/src/Migration/Logging/Log/CannotReadEntityCountLog.php index e3e55641b..70cd3af77 100644 --- a/src/Migration/Logging/Log/CannotReadEntityCountLog.php +++ b/src/Migration/Logging/Log/CannotReadEntityCountLog.php @@ -8,19 +8,14 @@ namespace SwagMigrationAssistant\Migration\Logging\Log; use Shopware\Core\Framework\Log\Package; +use SwagMigrationAssistant\Migration\Logging\Log\Builder\AbstractMigrationLogEntry; #[Package('fundamentals@after-sales')] -class CannotReadEntityCountLog extends BaseRunLogEntry +readonly class CannotReadEntityCountLog extends AbstractMigrationLogEntry { - public function __construct( - string $runUuid, - string $entity, - private readonly string $table, - private readonly ?string $condition, - private readonly string $exceptionCode, - private readonly string $exceptionMessage, - ) { - parent::__construct($runUuid, $entity); + public function isUserFixable(): bool + { + return false; } public function getLevel(): string @@ -32,36 +27,4 @@ public function getCode(): string { return 'SWAG_MIGRATION__COULD_NOT_READ_ENTITY_COUNT'; } - - public function getTitle(): string - { - return 'Could not read entity count'; - } - - /** - * @return array{entity: ?string, table: string, condition: ?string, exceptionCode: string, exceptionMessage: string} - */ - public function getParameters(): array - { - return [ - 'entity' => $this->getEntity(), - 'table' => $this->table, - 'condition' => $this->condition, - 'exceptionCode' => $this->exceptionCode, - 'exceptionMessage' => $this->exceptionMessage, - ]; - } - - public function getDescription(): string - { - $args = $this->getParameters(); - - return \sprintf( - 'Total count for entity %s could not be read. Make sure the table %s exists in your source system and the optional condition "%s" is valid. Exception message: %s', - $args['entity'], - $args['table'], - $args['condition'], - $args['exceptionMessage'] - ); - } } diff --git a/src/Migration/Logging/Log/DataSetNotFoundLog.php b/src/Migration/Logging/Log/DataSetNotFoundLog.php index 1119a2bbd..72b4bc6f1 100644 --- a/src/Migration/Logging/Log/DataSetNotFoundLog.php +++ b/src/Migration/Logging/Log/DataSetNotFoundLog.php @@ -8,17 +8,14 @@ namespace SwagMigrationAssistant\Migration\Logging\Log; use Shopware\Core\Framework\Log\Package; +use SwagMigrationAssistant\Migration\Logging\Log\Builder\AbstractMigrationLogEntry; #[Package('fundamentals@after-sales')] -class DataSetNotFoundLog extends BaseRunLogEntry +readonly class DataSetNotFoundLog extends AbstractMigrationLogEntry { - public function __construct( - string $runUuid, - string $entity, - string $sourceId, - private readonly string $profileName, - ) { - parent::__construct($runUuid, $entity, $sourceId); + public function isUserFixable(): bool + { + return false; } public function getLevel(): string @@ -30,33 +27,4 @@ public function getCode(): string { return 'SWAG_MIGRATION__DATASET_NOT_FOUND'; } - - public function getTitle(): string - { - return 'DataSet not found'; - } - - /** - * @return array{profileName: string, entity: ?string, sourceId: ?string} - */ - public function getParameters(): array - { - return [ - 'profileName' => $this->profileName, - 'entity' => $this->getEntity(), - 'sourceId' => $this->getSourceId(), - ]; - } - - public function getDescription(): string - { - $args = $this->getParameters(); - - return \sprintf( - 'DataSet for profile "%s" and entity "%s" not found. Entity with id "%s" could not be processed.', - $args['profileName'], - $args['entity'], - $args['sourceId'] - ); - } } diff --git a/src/Migration/Logging/Log/DebugLog.php b/src/Migration/Logging/Log/DebugLog.php index e916e2295..758c090c3 100644 --- a/src/Migration/Logging/Log/DebugLog.php +++ b/src/Migration/Logging/Log/DebugLog.php @@ -8,76 +8,96 @@ namespace SwagMigrationAssistant\Migration\Logging\Log; use Shopware\Core\Framework\Log\Package; +use SwagMigrationAssistant\Migration\Logging\Log\Builder\AbstractMigrationLogEntry; +use SwagMigrationAssistant\Migration\Logging\Log\Builder\MigrationLogEntry; #[Package('fundamentals@after-sales')] -class DebugLog implements LogEntryInterface +readonly class DebugLog implements MigrationLogEntry { /** - * @param array $logData + * @param array $logData */ public function __construct( - private readonly array $logData, - private readonly ?string $runId, + private string $runId, + private array $logData, ) { } - public function getLevel(): string + /** + * @return array + */ + public function getLogData(): array { - return self::LOG_LEVEL_DEBUG; + return $this->logData; } - public function getCode(): string + public function getRunId(): string { - return 'SWAG_MIGRATION__DEBUG'; + return $this->runId; } - public function getTitle(): string + public function isUserFixable(): bool { - return 'Debug'; + return false; } - /** - * @return array{logData: array} - */ - public function getParameters(): array + public function getProfileName(): string { - return [ - 'logData' => $this->logData, - ]; + return 'Debug Profile'; } - public function getDescription(): string + public function getGatewayName(): string { - return (string) \json_encode($this->logData); + return 'Debug Gateway'; } - public function getSnippetRoot(): string + public function getLevel(): string { - return 'swag-migration.index.error'; + return AbstractMigrationLogEntry::LOG_LEVEL_DEBUG; } - public function getTitleSnippet(): string + public function getCode(): string { - return \sprintf('%s.%s.title', $this->getSnippetRoot(), $this->getCode()); + return 'SWAG_MIGRATION__DEBUG'; } - public function getDescriptionSnippet(): string + public function getEntityName(): ?string { - return \sprintf('%s.%s.description', $this->getSnippetRoot(), $this->getCode()); + return null; } - public function getEntity(): ?string + public function getFieldName(): ?string { return null; } - public function getSourceId(): ?string + public function getFieldSourcePath(): ?string { return null; } - public function getRunId(): ?string + public function getSourceData(): ?array { - return $this->runId; + return null; + } + + public function getConvertedData(): ?array + { + return null; + } + + public function getExceptionMessage(): ?string + { + return null; + } + + public function getExceptionTrace(): ?array + { + return null; + } + + public function getEntityId(): ?string + { + return null; } } diff --git a/src/Migration/Logging/Log/DocumentTypeNotSupported.php b/src/Migration/Logging/Log/DocumentTypeNotSupported.php deleted file mode 100644 index 09338f098..000000000 --- a/src/Migration/Logging/Log/DocumentTypeNotSupported.php +++ /dev/null @@ -1,60 +0,0 @@ - - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace SwagMigrationAssistant\Migration\Logging\Log; - -use Shopware\Core\Framework\Log\Package; -use SwagMigrationAssistant\Migration\DataSelection\DefaultEntities; - -#[Package('fundamentals@after-sales')] -class DocumentTypeNotSupported extends BaseRunLogEntry -{ - public function __construct( - string $runId, - string $sourceId, - private readonly string $type, - ) { - parent::__construct($runId, DefaultEntities::ORDER_DOCUMENT, $sourceId); - } - - public function getLevel(): string - { - return self::LOG_LEVEL_WARNING; - } - - public function getCode(): string - { - return 'SWAG_MIGRATION__DOCUMENT_TYPE_NOT_SUPPORTED'; - } - - public function getTitle(): string - { - return 'Document type is not supported'; - } - - /** - * @return array{sourceId: ?string, type: string} - */ - public function getParameters(): array - { - return [ - 'sourceId' => $this->getSourceId(), - 'type' => $this->type, - ]; - } - - public function getDescription(): string - { - $args = $this->getParameters(); - - return \sprintf( - 'The document with the source id "%s" has the document type "%s", which just got migrated but is still missing a document renderer. If you want to generate documents of this type, please follow this documentation: https://developer.shopware.com/docs/guides/plugins/plugins/checkout/document/add-custom-document-type.html', - $args['sourceId'], - $args['type'] - ); - } -} diff --git a/src/Migration/Logging/Log/DocumentTypeNotSupportedLog.php b/src/Migration/Logging/Log/DocumentTypeNotSupportedLog.php new file mode 100644 index 000000000..6eed88c34 --- /dev/null +++ b/src/Migration/Logging/Log/DocumentTypeNotSupportedLog.php @@ -0,0 +1,30 @@ + + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace SwagMigrationAssistant\Migration\Logging\Log; + +use Shopware\Core\Framework\Log\Package; +use SwagMigrationAssistant\Migration\Logging\Log\Builder\AbstractMigrationLogEntry; + +#[Package('fundamentals@after-sales')] +readonly class DocumentTypeNotSupportedLog extends AbstractMigrationLogEntry +{ + public function isUserFixable(): bool + { + return false; + } + + public function getLevel(): string + { + return self::LOG_LEVEL_WARNING; + } + + public function getCode(): string + { + return 'SWAG_MIGRATION__DOCUMENT_TYPE_NOT_SUPPORTED'; + } +} diff --git a/src/Migration/Logging/Log/EmptyNecessaryFieldRunLog.php b/src/Migration/Logging/Log/EmptyNecessaryFieldRunLog.php index ccfce6da1..0115a2383 100644 --- a/src/Migration/Logging/Log/EmptyNecessaryFieldRunLog.php +++ b/src/Migration/Logging/Log/EmptyNecessaryFieldRunLog.php @@ -8,75 +8,23 @@ namespace SwagMigrationAssistant\Migration\Logging\Log; use Shopware\Core\Framework\Log\Package; +use SwagMigrationAssistant\Migration\Logging\Log\Builder\AbstractMigrationLogEntry; #[Package('fundamentals@after-sales')] -class EmptyNecessaryFieldRunLog extends BaseRunLogEntry +readonly class EmptyNecessaryFieldRunLog extends AbstractMigrationLogEntry { - public function __construct( - string $runId, - string $entity, - string $sourceId, - private readonly string $emptyField, - ) { - parent::__construct($runId, $entity, $sourceId); + public function isUserFixable(): bool + { + return false; } public function getCode(): string { - $entity = $this->getEntity(); - if ($entity === null) { - return 'SWAG_MIGRATION_EMPTY_NECESSARY_FIELD'; - } - - return \sprintf('SWAG_MIGRATION_EMPTY_NECESSARY_FIELD_%s', \mb_strtoupper($entity)); + return 'SWAG_MIGRATION_EMPTY_NECESSARY_FIELD'; } public function getLevel(): string { return self::LOG_LEVEL_WARNING; } - - public function getTitle(): string - { - $entity = $this->getEntity(); - if ($entity === null) { - return 'The entity has one or more empty necessary fields'; - } - - return \sprintf('The %s entity has one or more empty necessary fields', $entity); - } - - /** - * @return array{entity: ?string, sourceId: ?string, emptyField: string} - */ - public function getParameters(): array - { - return [ - 'entity' => $this->getEntity(), - 'sourceId' => $this->getSourceId(), - 'emptyField' => $this->emptyField, - ]; - } - - public function getDescription(): string - { - $args = $this->getParameters(); - - return \sprintf( - 'The %s entity with the source id %s does not have the necessary data for the field(s): %s', - $args['entity'], - $args['sourceId'], - $args['emptyField'] - ); - } - - public function getTitleSnippet(): string - { - return \sprintf('%s.%s.title', $this->getSnippetRoot(), 'SWAG_MIGRATION__SHOPWARE_EMPTY_NECESSARY_DATA_FIELDS'); - } - - public function getDescriptionSnippet(): string - { - return \sprintf('%s.%s.description', $this->getSnippetRoot(), 'SWAG_MIGRATION__SHOPWARE_EMPTY_NECESSARY_DATA_FIELDS'); - } } diff --git a/src/Migration/Logging/Log/EntityAlreadyExistsRunLog.php b/src/Migration/Logging/Log/EntityAlreadyExistsRunLog.php index f176f71fc..b83b49153 100644 --- a/src/Migration/Logging/Log/EntityAlreadyExistsRunLog.php +++ b/src/Migration/Logging/Log/EntityAlreadyExistsRunLog.php @@ -8,16 +8,14 @@ namespace SwagMigrationAssistant\Migration\Logging\Log; use Shopware\Core\Framework\Log\Package; +use SwagMigrationAssistant\Migration\Logging\Log\Builder\AbstractMigrationLogEntry; #[Package('fundamentals@after-sales')] -class EntityAlreadyExistsRunLog extends BaseRunLogEntry +readonly class EntityAlreadyExistsRunLog extends AbstractMigrationLogEntry { - public function __construct( - string $runId, - string $entity, - string $sourceId, - ) { - parent::__construct($runId, $entity, $sourceId); + public function isUserFixable(): bool + { + return false; } public function getLevel(): string @@ -27,53 +25,6 @@ public function getLevel(): string public function getCode(): string { - $entity = $this->getEntity(); - if ($entity === null) { - return 'SWAG_MIGRATION_ENTITY_ALREADY_EXISTS'; - } - - return \sprintf('SWAG_MIGRATION_%s_ENTITY_ALREADY_EXISTS', \mb_strtoupper($entity)); - } - - public function getTitle(): string - { - $entity = $this->getEntity(); - if ($entity === null) { - return 'The entity already exists'; - } - - return \sprintf('The %s entity already exists', $entity); - } - - /** - * @return array{entity: ?string, sourceId: ?string} - */ - public function getParameters(): array - { - return [ - 'entity' => $this->getEntity(), - 'sourceId' => $this->getSourceId(), - ]; - } - - public function getDescription(): string - { - $args = $this->getParameters(); - - return \sprintf( - 'The %s entity with source id "%s" already exists and cannot be written.', - $args['entity'], - $args['sourceId'] - ); - } - - public function getTitleSnippet(): string - { - return \sprintf('%s.%s.title', $this->getSnippetRoot(), 'SWAG_MIGRATION_ENTITY_ALREADY_EXISTS'); - } - - public function getDescriptionSnippet(): string - { - return \sprintf('%s.%s.description', $this->getSnippetRoot(), 'SWAG_MIGRATION_ENTITY_ALREADY_EXISTS'); + return 'SWAG_MIGRATION_ENTITY_ALREADY_EXISTS'; } } diff --git a/src/Migration/Logging/Log/ExceptionRunLog.php b/src/Migration/Logging/Log/ExceptionRunLog.php index 5e558213a..1576d4464 100644 --- a/src/Migration/Logging/Log/ExceptionRunLog.php +++ b/src/Migration/Logging/Log/ExceptionRunLog.php @@ -8,18 +8,14 @@ namespace SwagMigrationAssistant\Migration\Logging\Log; use Shopware\Core\Framework\Log\Package; -use Shopware\Core\Framework\ShopwareHttpException; +use SwagMigrationAssistant\Migration\Logging\Log\Builder\AbstractMigrationLogEntry; #[Package('fundamentals@after-sales')] -class ExceptionRunLog extends BaseRunLogEntry +readonly class ExceptionRunLog extends AbstractMigrationLogEntry { - public function __construct( - string $runId, - string $entity, - private readonly \Throwable $exception, - ?string $sourceId = null, - ) { - parent::__construct($runId, $entity, $sourceId); + public function isUserFixable(): bool + { + return false; } public function getLevel(): string @@ -31,42 +27,4 @@ public function getCode(): string { return 'SWAG_MIGRATION_RUN_EXCEPTION'; } - - public function getTitle(): string - { - return 'An exception occurred'; - } - - /** - * @return array{entity: ?string, sourceId: ?string, exceptionCode: int|string, exceptionMessage: ?string, exceptionFile: string, exceptionLine: int, exceptionTrace: ?string, description: string} - */ - public function getParameters(): array - { - $entity = $this->getEntity() ?? '-'; - $errorCode = $this->exception->getCode(); - if (\is_subclass_of($this->exception, ShopwareHttpException::class)) { - $errorCode = $this->exception->getErrorCode(); - } - - return [ - 'entity' => $this->getEntity(), - 'sourceId' => $this->getSourceId(), - 'exceptionCode' => $errorCode, - 'exceptionMessage' => \preg_replace('/[[:^print:]]/', '', $this->exception->getMessage()), - 'exceptionFile' => $this->exception->getFile(), - 'exceptionLine' => $this->exception->getLine(), - 'exceptionTrace' => \preg_replace('/[[:^print:]]/', '', $this->exception->getTraceAsString()), - 'description' => \sprintf( - 'Entity: %s, sourceId: %s' . \PHP_EOL . '%s', - $entity, - $this->getSourceId() ?? '-', - \preg_replace('/[[:^print:]]/', '', $this->exception->getMessage()) - ), - ]; - } - - public function getDescription(): string - { - return $this->getParameters()['description']; - } } diff --git a/src/Migration/Logging/Log/FieldReassignedRunLog.php b/src/Migration/Logging/Log/FieldReassignedRunLog.php index e47519f69..2e0b91d87 100644 --- a/src/Migration/Logging/Log/FieldReassignedRunLog.php +++ b/src/Migration/Logging/Log/FieldReassignedRunLog.php @@ -8,18 +8,14 @@ namespace SwagMigrationAssistant\Migration\Logging\Log; use Shopware\Core\Framework\Log\Package; +use SwagMigrationAssistant\Migration\Logging\Log\Builder\AbstractMigrationLogEntry; #[Package('fundamentals@after-sales')] -class FieldReassignedRunLog extends BaseRunLogEntry +readonly class FieldReassignedRunLog extends AbstractMigrationLogEntry { - public function __construct( - string $runId, - string $entity, - string $sourceId, - private readonly string $emptyField, - private readonly string $replacementField, - ) { - parent::__construct($runId, $entity, $sourceId); + public function isUserFixable(): bool + { + return false; } public function getLevel(): string @@ -29,57 +25,6 @@ public function getLevel(): string public function getCode(): string { - $entity = $this->getEntity(); - if ($entity === null) { - return 'SWAG_MIGRATION_ENTITY_FIELD_REASSIGNED'; - } - - return \sprintf('SWAG_MIGRATION_%s_ENTITY_FIELD_REASSIGNED', \mb_strtoupper($entity)); - } - - public function getTitle(): string - { - $entity = $this->getEntity(); - if ($entity === null) { - return 'The entity has a field that was reassigned'; - } - - return \sprintf('The %s entity has a field that was reassigned', $entity); - } - - /** - * @return array{entity: ?string, sourceId: ?string, emptyField: string, replacementField: string} - */ - public function getParameters(): array - { - return [ - 'entity' => $this->getEntity(), - 'sourceId' => $this->getSourceId(), - 'emptyField' => $this->emptyField, - 'replacementField' => $this->replacementField, - ]; - } - - public function getDescription(): string - { - $args = $this->getParameters(); - - return \sprintf( - 'The %s entity with the source id "%s" got the field %s replaced with %s.', - $args['entity'], - $args['sourceId'], - $args['emptyField'], - $args['replacementField'] - ); - } - - public function getTitleSnippet(): string - { - return \sprintf('%s.%s.title', $this->getSnippetRoot(), 'SWAG_MIGRATION_ENTITY_FIELD_REASSIGNED'); - } - - public function getDescriptionSnippet(): string - { - return \sprintf('%s.%s.description', $this->getSnippetRoot(), 'SWAG_MIGRATION_ENTITY_FIELD_REASSIGNED'); + return 'SWAG_MIGRATION_ENTITY_FIELD_REASSIGNED'; } } diff --git a/src/Migration/Logging/Log/InvalidUnserializedData.php b/src/Migration/Logging/Log/InvalidUnserializedData.php deleted file mode 100644 index dabdad73b..000000000 --- a/src/Migration/Logging/Log/InvalidUnserializedData.php +++ /dev/null @@ -1,65 +0,0 @@ - - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace SwagMigrationAssistant\Migration\Logging\Log; - -use Shopware\Core\Framework\Log\Package; - -#[Package('fundamentals@after-sales')] -class InvalidUnserializedData extends BaseRunLogEntry -{ - public function __construct( - string $runId, - string $entity, - string $sourceId, - private readonly string $unserializedEntity, - private readonly string $serializedData, - ) { - parent::__construct($runId, $entity, $sourceId); - } - - public function getLevel(): string - { - return self::LOG_LEVEL_WARNING; - } - - public function getCode(): string - { - return 'SWAG_MIGRATION__SHOPWARE_INVALID_UNSERIALIZED_DATA'; - } - - public function getTitle(): string - { - return 'Invalid unserialized data'; - } - - /** - * @return array{entity: ?string, sourceId: ?string, unserializedEntity: string, serializedData: string} - */ - public function getParameters(): array - { - return [ - 'entity' => $this->getEntity(), - 'sourceId' => $this->getSourceId(), - 'unserializedEntity' => $this->unserializedEntity, - 'serializedData' => $this->serializedData, - ]; - } - - public function getDescription(): string - { - $args = $this->getParameters(); - - return \sprintf( - 'The %s entity with source id "%s" could not be converted because of invalid unserialized object data for the "%s" entity and the raw data is: %s', - $args['entity'], - $args['sourceId'], - $args['unserializedEntity'], - $args['serializedData'] - ); - } -} diff --git a/src/Migration/Logging/Log/InvalidUnserializedDataLog.php b/src/Migration/Logging/Log/InvalidUnserializedDataLog.php new file mode 100644 index 000000000..ac366a2b8 --- /dev/null +++ b/src/Migration/Logging/Log/InvalidUnserializedDataLog.php @@ -0,0 +1,30 @@ + + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace SwagMigrationAssistant\Migration\Logging\Log; + +use Shopware\Core\Framework\Log\Package; +use SwagMigrationAssistant\Migration\Logging\Log\Builder\AbstractMigrationLogEntry; + +#[Package('fundamentals@after-sales')] +readonly class InvalidUnserializedDataLog extends AbstractMigrationLogEntry +{ + public function isUserFixable(): bool + { + return false; + } + + public function getLevel(): string + { + return self::LOG_LEVEL_WARNING; + } + + public function getCode(): string + { + return 'SWAG_MIGRATION__SHOPWARE_INVALID_UNSERIALIZED_DATA'; + } +} diff --git a/src/Migration/Logging/Log/LogEntryInterface.php b/src/Migration/Logging/Log/LogEntryInterface.php deleted file mode 100644 index 68d964b15..000000000 --- a/src/Migration/Logging/Log/LogEntryInterface.php +++ /dev/null @@ -1,42 +0,0 @@ - - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace SwagMigrationAssistant\Migration\Logging\Log; - -use Shopware\Core\Framework\Log\Package; - -#[Package('fundamentals@after-sales')] -interface LogEntryInterface -{ - final public const LOG_LEVEL_INFO = 'info'; - final public const LOG_LEVEL_WARNING = 'warning'; - final public const LOG_LEVEL_ERROR = 'error'; - final public const LOG_LEVEL_DEBUG = 'debug'; - - public function getLevel(): string; - - public function getCode(): string; - - public function getTitle(): string; - - /** - * @return array - */ - public function getParameters(): array; - - public function getDescription(): string; - - public function getTitleSnippet(): string; - - public function getDescriptionSnippet(): string; - - public function getEntity(): ?string; - - public function getSourceId(): ?string; - - public function getRunId(): ?string; -} diff --git a/src/Migration/Logging/Log/MainVariantRelationNotConverted.php b/src/Migration/Logging/Log/MainVariantRelationNotConverted.php new file mode 100644 index 000000000..f1c391502 --- /dev/null +++ b/src/Migration/Logging/Log/MainVariantRelationNotConverted.php @@ -0,0 +1,30 @@ + + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace SwagMigrationAssistant\Migration\Logging\Log; + +use Shopware\Core\Framework\Log\Package; +use SwagMigrationAssistant\Migration\Logging\Log\Builder\AbstractMigrationLogEntry; + +#[Package('after-sales')] +readonly class MainVariantRelationNotConverted extends AbstractMigrationLogEntry +{ + public function getLevel(): string + { + return self::LOG_LEVEL_ERROR; + } + + public function getCode(): string + { + return 'SWAG_MIGRATION__MAIN_VARIANT_RELATION_NOT_CONVERTED'; + } + + public function isUserFixable(): bool + { + return false; + } +} diff --git a/src/Migration/Logging/Log/MessageQueueExceptionLog.php b/src/Migration/Logging/Log/MessageQueueExceptionLog.php index 36059d14f..bb28b1109 100644 --- a/src/Migration/Logging/Log/MessageQueueExceptionLog.php +++ b/src/Migration/Logging/Log/MessageQueueExceptionLog.php @@ -8,17 +8,14 @@ namespace SwagMigrationAssistant\Migration\Logging\Log; use Shopware\Core\Framework\Log\Package; -use Shopware\Core\Framework\ShopwareHttpException; +use SwagMigrationAssistant\Migration\Logging\Log\Builder\AbstractMigrationLogEntry; #[Package('fundamentals@after-sales')] -class MessageQueueExceptionLog extends BaseRunLogEntry +readonly class MessageQueueExceptionLog extends AbstractMigrationLogEntry { - public function __construct( - string $runId, - private readonly \Throwable $exception, - private int $exceptionCount, - ) { - parent::__construct($runId); + public function isUserFixable(): bool + { + return false; } public function getLevel(): string @@ -30,40 +27,4 @@ public function getCode(): string { return 'SWAG_MIGRATION_MESSAGE_QUEUE_EXCEPTION'; } - - public function getTitle(): string - { - return 'An exception occurred during the message queue processing'; - } - - /** - * @return array{exceptionCode: int|string, exceptionMessage: ?string, exceptionFile: string, exceptionLine: int, exceptionTrace: ?string, description: string} - */ - public function getParameters(): array - { - $errorCode = $this->exception->getCode(); - if (\is_subclass_of($this->exception, ShopwareHttpException::class)) { - $errorCode = $this->exception->getErrorCode(); - } - - return [ - 'exceptionCount' => $this->exceptionCount, - 'exceptionCode' => $errorCode, - 'exceptionMessage' => \preg_replace('/[[:^print:]]/', '', $this->exception->getMessage()), - 'exceptionFile' => $this->exception->getFile(), - 'exceptionLine' => $this->exception->getLine(), - 'exceptionTrace' => \preg_replace('/[[:^print:]]/', '', $this->exception->getTraceAsString()), - 'description' => \sprintf( - 'RunId: %s, ExceptionCount: %d ' . \PHP_EOL . '%s', - $this->getRunId(), - $this->exceptionCount, - \preg_replace('/[[:^print:]]/', '', $this->exception->getMessage()) - ), - ]; - } - - public function getDescription(): string - { - return $this->getParameters()['description']; - } } diff --git a/src/Migration/Logging/Log/MimeTypeErrorLog.php b/src/Migration/Logging/Log/MimeTypeErrorLog.php index a38790d1d..ba02236ae 100644 --- a/src/Migration/Logging/Log/MimeTypeErrorLog.php +++ b/src/Migration/Logging/Log/MimeTypeErrorLog.php @@ -8,16 +8,14 @@ namespace SwagMigrationAssistant\Migration\Logging\Log; use Shopware\Core\Framework\Log\Package; +use SwagMigrationAssistant\Migration\Logging\Log\Builder\AbstractMigrationLogEntry; #[Package('fundamentals@after-sales')] -class MimeTypeErrorLog extends BaseRunLogEntry +readonly class MimeTypeErrorLog extends AbstractMigrationLogEntry { - public function __construct( - string $runId, - string $entity, - ?string $sourceId = null, - ) { - parent::__construct($runId, $entity, $sourceId); + public function isUserFixable(): bool + { + return false; } public function getLevel(): string @@ -29,27 +27,4 @@ public function getCode(): string { return 'SWAG_MIGRATION__MIME_TYPE_COULD_NOT_BE_DETERMINED'; } - - public function getTitle(): string - { - return 'An exception occurred'; - } - - /** - * @return array{entity: ?string, sourceId: ?string, exceptionCode: int|string, description: string} - */ - public function getParameters(): array - { - return [ - 'entity' => $this->getEntity(), - 'sourceId' => $this->getSourceId(), - 'exceptionCode' => $this->getCode(), - 'description' => 'Could not determine the mime type', - ]; - } - - public function getDescription(): string - { - return $this->getParameters()['description']; - } } diff --git a/src/Migration/Logging/Log/NotConvertedLog.php b/src/Migration/Logging/Log/NotConvertedLog.php new file mode 100644 index 000000000..064de37f9 --- /dev/null +++ b/src/Migration/Logging/Log/NotConvertedLog.php @@ -0,0 +1,30 @@ + + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace SwagMigrationAssistant\Migration\Logging\Log; + +use Shopware\Core\Framework\Log\Package; +use SwagMigrationAssistant\Migration\Logging\Log\Builder\AbstractMigrationLogEntry; + +#[Package('after-sales')] +readonly class NotConvertedLog extends AbstractMigrationLogEntry +{ + public function getLevel(): string + { + return self::LOG_LEVEL_INFO; + } + + public function getCode(): string + { + return 'SWAG_MIGRATION__ENTITY_NOT_CONVERTED'; + } + + public function isUserFixable(): bool + { + return false; + } +} diff --git a/src/Migration/Logging/Log/ProcessorNotFoundLog.php b/src/Migration/Logging/Log/ProcessorNotFoundLog.php index 2ade8210d..13f953088 100644 --- a/src/Migration/Logging/Log/ProcessorNotFoundLog.php +++ b/src/Migration/Logging/Log/ProcessorNotFoundLog.php @@ -8,16 +8,14 @@ namespace SwagMigrationAssistant\Migration\Logging\Log; use Shopware\Core\Framework\Log\Package; +use SwagMigrationAssistant\Migration\Logging\Log\Builder\AbstractMigrationLogEntry; #[Package('fundamentals@after-sales')] -class ProcessorNotFoundLog implements LogEntryInterface +readonly class ProcessorNotFoundLog extends AbstractMigrationLogEntry { - public function __construct( - private readonly string $runId, - private readonly string $entity, - private readonly string $profileName, - private readonly string $gatewayName, - ) { + public function isUserFixable(): bool + { + return false; } public function getLevel(): string @@ -29,63 +27,4 @@ public function getCode(): string { return 'SWAG_MIGRATION__PROCESSOR_NOT_FOUND'; } - - public function getTitle(): string - { - return 'Processor not found'; - } - - /** - * @return array{profileName: string, gatewayName: string, entity: ?string} - */ - public function getParameters(): array - { - return [ - 'profileName' => $this->profileName, - 'gatewayName' => $this->gatewayName, - 'entity' => $this->getEntity(), - ]; - } - - public function getDescription(): string - { - $args = $this->getParameters(); - - return \sprintf( - 'Processor for profile "%s", gateway "%s" and entity "%s" not found.', - $args['profileName'], - $args['gatewayName'], - $args['entity'] - ); - } - - public function getEntity(): ?string - { - return $this->entity; - } - - public function getSourceId(): ?string - { - return null; - } - - public function getRunId(): ?string - { - return $this->runId; - } - - public function getSnippetRoot(): string - { - return 'swag-migration.index.error'; - } - - public function getTitleSnippet(): string - { - return \sprintf('%s.%s.title', $this->getSnippetRoot(), $this->getCode()); - } - - public function getDescriptionSnippet(): string - { - return \sprintf('%s.%s.description', $this->getSnippetRoot(), $this->getCode()); - } } diff --git a/src/Migration/Logging/Log/RunAbortedAutomatically.php b/src/Migration/Logging/Log/RunAbortedAutomatically.php deleted file mode 100644 index 6c05e828e..000000000 --- a/src/Migration/Logging/Log/RunAbortedAutomatically.php +++ /dev/null @@ -1,66 +0,0 @@ - - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace SwagMigrationAssistant\Migration\Logging\Log; - -use Shopware\Core\Framework\Log\Package; -use Shopware\Core\Framework\ShopwareHttpException; - -#[Package('fundamentals@after-sales')] -class RunAbortedAutomatically extends BaseRunLogEntry -{ - public function __construct( - string $runId, - private readonly \Throwable $exception, - ) { - parent::__construct($runId); - } - - public function getLevel(): string - { - return self::LOG_LEVEL_ERROR; - } - - public function getCode(): string - { - return 'SWAG_MIGRATION_RUN_ABORTED_AUTOMATICALLY_EXCEPTION'; - } - - public function getTitle(): string - { - return 'Run was aborted automatically, because too many consecutive exceptions occurred'; - } - - /** - * @return array{exceptionCode: int|string, exceptionMessage: ?string, exceptionFile: string, exceptionLine: int, exceptionTrace: ?string, description: string} - */ - public function getParameters(): array - { - $errorCode = $this->exception->getCode(); - if (\is_subclass_of($this->exception, ShopwareHttpException::class)) { - $errorCode = $this->exception->getErrorCode(); - } - - return [ - 'exceptionCode' => $errorCode, - 'exceptionMessage' => \preg_replace('/[[:^print:]]/', '', $this->exception->getMessage()), - 'exceptionFile' => $this->exception->getFile(), - 'exceptionLine' => $this->exception->getLine(), - 'exceptionTrace' => \preg_replace('/[[:^print:]]/', '', $this->exception->getTraceAsString()), - 'description' => \sprintf( - 'RunId: %s ' . \PHP_EOL . '%s', - $this->getRunId(), - \preg_replace('/[[:^print:]]/', '', $this->exception->getMessage()) - ), - ]; - } - - public function getDescription(): string - { - return $this->getParameters()['description']; - } -} diff --git a/src/Migration/Logging/Log/RunAbortedAutomaticallyLog.php b/src/Migration/Logging/Log/RunAbortedAutomaticallyLog.php new file mode 100644 index 000000000..1f164b736 --- /dev/null +++ b/src/Migration/Logging/Log/RunAbortedAutomaticallyLog.php @@ -0,0 +1,30 @@ + + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace SwagMigrationAssistant\Migration\Logging\Log; + +use Shopware\Core\Framework\Log\Package; +use SwagMigrationAssistant\Migration\Logging\Log\Builder\AbstractMigrationLogEntry; + +#[Package('fundamentals@after-sales')] +readonly class RunAbortedAutomaticallyLog extends AbstractMigrationLogEntry +{ + public function isUserFixable(): bool + { + return false; + } + + public function getLevel(): string + { + return self::LOG_LEVEL_ERROR; + } + + public function getCode(): string + { + return 'SWAG_MIGRATION_RUN_ABORTED_AUTOMATICALLY_EXCEPTION'; + } +} diff --git a/src/Migration/Logging/Log/TemporaryFileErrorLog.php b/src/Migration/Logging/Log/TemporaryFileErrorLog.php index eb4640485..e24c66b08 100644 --- a/src/Migration/Logging/Log/TemporaryFileErrorLog.php +++ b/src/Migration/Logging/Log/TemporaryFileErrorLog.php @@ -8,16 +8,14 @@ namespace SwagMigrationAssistant\Migration\Logging\Log; use Shopware\Core\Framework\Log\Package; +use SwagMigrationAssistant\Migration\Logging\Log\Builder\AbstractMigrationLogEntry; #[Package('fundamentals@after-sales')] -class TemporaryFileErrorLog extends BaseRunLogEntry +readonly class TemporaryFileErrorLog extends AbstractMigrationLogEntry { - public function __construct( - string $runId, - string $entity, - ?string $sourceId = null, - ) { - parent::__construct($runId, $entity, $sourceId); + public function isUserFixable(): bool + { + return false; } public function getLevel(): string @@ -29,27 +27,4 @@ public function getCode(): string { return 'SWAG_MIGRATION__TEMPORARY_FILE_COULD_NOT_BE_CREATED'; } - - public function getTitle(): string - { - return 'An exception occurred'; - } - - /** - * @return array{entity: ?string, sourceId: ?string, exceptionCode: int|string, description: string} - */ - public function getParameters(): array - { - return [ - 'entity' => $this->getEntity(), - 'sourceId' => $this->getSourceId(), - 'exceptionCode' => $this->getCode(), - 'description' => 'The temporary file for media download could not be created', - ]; - } - - public function getDescription(): string - { - return $this->getParameters()['description']; - } } diff --git a/src/Migration/Logging/Log/ThemeCompilingErrorRunLog.php b/src/Migration/Logging/Log/ThemeCompilingErrorRunLog.php index 667ba2229..751a30e82 100644 --- a/src/Migration/Logging/Log/ThemeCompilingErrorRunLog.php +++ b/src/Migration/Logging/Log/ThemeCompilingErrorRunLog.php @@ -8,15 +8,14 @@ namespace SwagMigrationAssistant\Migration\Logging\Log; use Shopware\Core\Framework\Log\Package; +use SwagMigrationAssistant\Migration\Logging\Log\Builder\AbstractMigrationLogEntry; #[Package('fundamentals@after-sales')] -class ThemeCompilingErrorRunLog extends BaseRunLogEntry +readonly class ThemeCompilingErrorRunLog extends AbstractMigrationLogEntry { - public function __construct( - string $runId, - string $sourceId, - ) { - parent::__construct($runId, null, $sourceId); + public function isUserFixable(): bool + { + return false; } public function getLevel(): string @@ -28,29 +27,4 @@ public function getCode(): string { return 'SWAG_MIGRATION__THEME_COMPILING_ERROR'; } - - public function getTitle(): string - { - return 'Theme compiling error'; - } - - /** - * @return array{sourceId: ?string} - */ - public function getParameters(): array - { - return [ - 'sourceId' => $this->getSourceId(), - ]; - } - - public function getDescription(): string - { - $args = $this->getParameters(); - - return \sprintf( - 'The theme with id "%s" could not be compiled.', - $args['sourceId'] - ); - } } diff --git a/src/Migration/Logging/Log/UnknownEntityLog.php b/src/Migration/Logging/Log/UnknownEntityLog.php index 428d3c3c8..a8de064e2 100644 --- a/src/Migration/Logging/Log/UnknownEntityLog.php +++ b/src/Migration/Logging/Log/UnknownEntityLog.php @@ -8,18 +8,14 @@ namespace SwagMigrationAssistant\Migration\Logging\Log; use Shopware\Core\Framework\Log\Package; +use SwagMigrationAssistant\Migration\Logging\Log\Builder\AbstractMigrationLogEntry; #[Package('fundamentals@after-sales')] -class UnknownEntityLog extends BaseRunLogEntry +readonly class UnknownEntityLog extends AbstractMigrationLogEntry { - public function __construct( - string $runId, - string $entity, - string $sourceId, - private readonly string $requiredForEntity, - private readonly string $requiredForSourceId, - ) { - parent::__construct($runId, $entity, $sourceId); + public function isUserFixable(): bool + { + return false; } public function getLevel(): string @@ -29,57 +25,6 @@ public function getLevel(): string public function getCode(): string { - $entity = $this->getEntity(); - if ($entity === null) { - return 'SWAG_MIGRATION_ENTITY_UNKNOWN'; - } - - return \sprintf('SWAG_MIGRATION_%s_ENTITY_UNKNOWN', \mb_strtoupper($entity)); - } - - public function getTitle(): string - { - $entity = $this->getEntity(); - if ($entity === null) { - return 'Cannot find entity'; - } - - return \sprintf('Cannot find %s', $entity); - } - - /** - * @return array{requiredForEntity: string, requiredForSourceId: string, entity: ?string, sourceId: ?string} - */ - public function getParameters(): array - { - return [ - 'requiredForEntity' => $this->requiredForEntity, - 'requiredForSourceId' => $this->requiredForSourceId, - 'entity' => $this->getEntity(), - 'sourceId' => $this->getSourceId(), - ]; - } - - public function getDescription(): string - { - $args = $this->getParameters(); - - return \sprintf( - 'The %s entity with the source id "%s" cannot find the depended %s entity with the source id "%s".', - $args['requiredForEntity'], - $args['requiredForSourceId'], - $args['entity'], - $args['sourceId'] - ); - } - - public function getTitleSnippet(): string - { - return \sprintf('%s.%s.title', $this->getSnippetRoot(), 'SWAG_MIGRATION_ENTITY_UNKNOWN'); - } - - public function getDescriptionSnippet(): string - { - return \sprintf('%s.%s.description', $this->getSnippetRoot(), 'SWAG_MIGRATION_ENTITY_UNKNOWN'); + return 'SWAG_MIGRATION_ENTITY_UNKNOWN'; } } diff --git a/src/Migration/Logging/Log/UnsupportedObjectType.php b/src/Migration/Logging/Log/UnsupportedObjectType.php deleted file mode 100644 index df34e69b5..000000000 --- a/src/Migration/Logging/Log/UnsupportedObjectType.php +++ /dev/null @@ -1,62 +0,0 @@ - - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace SwagMigrationAssistant\Migration\Logging\Log; - -use Shopware\Core\Framework\Log\Package; - -#[Package('fundamentals@after-sales')] -class UnsupportedObjectType extends BaseRunLogEntry -{ - public function __construct( - string $runId, - private readonly string $type, - string $entity, - string $sourceId, - ) { - parent::__construct($runId, $entity, $sourceId); - } - - public function getLevel(): string - { - return self::LOG_LEVEL_WARNING; - } - - public function getCode(): string - { - return 'SWAG_MIGRATION__SHOPWARE_UNSUPPORTED_OBJECT_TYPE'; - } - - public function getTitle(): string - { - return 'Unsupported object type'; - } - - /** - * @return array{objectType: string, entity: ?string, sourceId: ?string} - */ - public function getParameters(): array - { - return [ - 'objectType' => $this->type, - 'entity' => $this->getEntity(), - 'sourceId' => $this->getSourceId(), - ]; - } - - public function getDescription(): string - { - $args = $this->getParameters(); - - return \sprintf( - '%s of object type "%s" with source id "%s" could not be converted.', - $args['entity'], - $args['objectType'], - $args['sourceId'] - ); - } -} diff --git a/src/Migration/Logging/Log/UnsupportedObjectTypeLog.php b/src/Migration/Logging/Log/UnsupportedObjectTypeLog.php new file mode 100644 index 000000000..1c56bb373 --- /dev/null +++ b/src/Migration/Logging/Log/UnsupportedObjectTypeLog.php @@ -0,0 +1,30 @@ + + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace SwagMigrationAssistant\Migration\Logging\Log; + +use Shopware\Core\Framework\Log\Package; +use SwagMigrationAssistant\Migration\Logging\Log\Builder\AbstractMigrationLogEntry; + +#[Package('fundamentals@after-sales')] +readonly class UnsupportedObjectTypeLog extends AbstractMigrationLogEntry +{ + public function isUserFixable(): bool + { + return false; + } + + public function getLevel(): string + { + return self::LOG_LEVEL_WARNING; + } + + public function getCode(): string + { + return 'SWAG_MIGRATION__SHOPWARE_UNSUPPORTED_OBJECT_TYPE'; + } +} diff --git a/src/Migration/Logging/Log/WriteExceptionRunLog.php b/src/Migration/Logging/Log/WriteExceptionRunLog.php index 32c192607..b3bded60c 100644 --- a/src/Migration/Logging/Log/WriteExceptionRunLog.php +++ b/src/Migration/Logging/Log/WriteExceptionRunLog.php @@ -8,20 +8,14 @@ namespace SwagMigrationAssistant\Migration\Logging\Log; use Shopware\Core\Framework\Log\Package; +use SwagMigrationAssistant\Migration\Logging\Log\Builder\AbstractMigrationLogEntry; #[Package('fundamentals@after-sales')] -class WriteExceptionRunLog extends BaseRunLogEntry +readonly class WriteExceptionRunLog extends AbstractMigrationLogEntry { - /** - * @param array $error - */ - public function __construct( - string $runId, - string $entity, - private readonly array $error, - ?string $dataId = null, - ) { - parent::__construct($runId, $entity, $dataId); + public function isUserFixable(): bool + { + return false; } public function getLevel(): string @@ -33,31 +27,4 @@ public function getCode(): string { return 'SWAG_MIGRATION__WRITE_EXCEPTION_OCCURRED'; } - - public function getTitle(): string - { - return 'A write exception has occurred'; - } - - /** - * @return array{entity: ?string, dataId: ?string, error: array, description: string} - */ - public function getParameters(): array - { - return [ - 'entity' => $this->getEntity(), - 'dataId' => $this->getSourceId(), - 'error' => $this->error, - 'description' => (string) \json_encode([ - 'entity' => $this->getEntity(), - 'dataId' => $this->getSourceId(), - 'error' => $this->error, - ], \JSON_PRETTY_PRINT), - ]; - } - - public function getDescription(): string - { - return $this->getParameters()['description']; - } } diff --git a/src/Migration/Logging/LoggingService.php b/src/Migration/Logging/LoggingService.php index 41f14bfaf..f1c22709a 100644 --- a/src/Migration/Logging/LoggingService.php +++ b/src/Migration/Logging/LoggingService.php @@ -11,7 +11,7 @@ use Shopware\Core\Framework\Context; use Shopware\Core\Framework\DataAbstractionLayer\EntityRepository; use Shopware\Core\Framework\Log\Package; -use SwagMigrationAssistant\Migration\Logging\Log\LogEntryInterface; +use SwagMigrationAssistant\Migration\Logging\Log\Builder\MigrationLogEntry; #[Package('fundamentals@after-sales')] class LoggingService implements LoggingServiceInterface @@ -51,22 +51,41 @@ public function saveLogging(Context $context): void } } - public function addLogEntry(LogEntryInterface $logEntry): void + public function addLogEntry(MigrationLogEntry $logEntry): void { $this->logging[] = [ + 'runId' => $logEntry->getRunId(), + 'profileName' => $logEntry->getProfileName(), + 'gatewayName' => $logEntry->getGatewayName(), 'level' => $logEntry->getLevel(), 'code' => $logEntry->getCode(), - 'title' => $logEntry->getTitle(), - 'description' => $logEntry->getDescription(), - 'parameters' => $logEntry->getParameters(), - 'titleSnippet' => $logEntry->getTitleSnippet(), - 'descriptionSnippet' => $logEntry->getDescriptionSnippet(), - 'entity' => $logEntry->getEntity(), - 'sourceId' => $logEntry->getSourceId(), - 'runId' => $logEntry->getRunId(), + 'userFixable' => $logEntry->isUserFixable(), + 'entityId' => $logEntry->getEntityId(), + 'entityName' => $logEntry->getEntityName(), + 'fieldName' => $logEntry->getFieldName(), + 'fieldSourcePath' => $logEntry->getFieldSourcePath(), + 'sourceData' => $logEntry->getSourceData(), + 'convertedData' => $logEntry->getConvertedData(), + 'exceptionMessage' => $logEntry->getExceptionMessage(), + 'exceptionTrace' => $logEntry->getExceptionTrace(), ]; } + /** + * @param array $keys + * @param callable(array-key $key, mixed|null $value): MigrationLogEntry $callback + */ + public function addLogForEach(array $keys, callable $callback): void + { + foreach ($keys as $key => $value) { + if (\array_is_list($keys)) { + $this->addLogEntry($callback($value, null)); + } else { + $this->addLogEntry($callback($key, $value)); + } + } + } + private function writePerEntry(Context $context): void { foreach ($this->logging as $log) { diff --git a/src/Migration/Logging/LoggingServiceInterface.php b/src/Migration/Logging/LoggingServiceInterface.php index 61416a10a..26c30301c 100644 --- a/src/Migration/Logging/LoggingServiceInterface.php +++ b/src/Migration/Logging/LoggingServiceInterface.php @@ -9,12 +9,18 @@ use Shopware\Core\Framework\Context; use Shopware\Core\Framework\Log\Package; -use SwagMigrationAssistant\Migration\Logging\Log\LogEntryInterface; +use SwagMigrationAssistant\Migration\Logging\Log\Builder\MigrationLogEntry; #[Package('fundamentals@after-sales')] interface LoggingServiceInterface { - public function addLogEntry(LogEntryInterface $logEntry): void; + public function addLogEntry(MigrationLogEntry $logEntry): void; + + /** + * @param array $keys + * @param callable(array-key $key, mixed|null $value): MigrationLogEntry $callback + */ + public function addLogForEach(array $keys, callable $callback): void; public function saveLogging(Context $context): void; } diff --git a/src/Migration/Logging/SwagMigrationLoggingDefinition.php b/src/Migration/Logging/SwagMigrationLoggingDefinition.php index 2b4287fac..3831502f0 100644 --- a/src/Migration/Logging/SwagMigrationLoggingDefinition.php +++ b/src/Migration/Logging/SwagMigrationLoggingDefinition.php @@ -9,13 +9,13 @@ use Shopware\Core\Framework\DataAbstractionLayer\EntityDefinition; use Shopware\Core\Framework\DataAbstractionLayer\Field\AutoIncrementField; +use Shopware\Core\Framework\DataAbstractionLayer\Field\BoolField; use Shopware\Core\Framework\DataAbstractionLayer\Field\CreatedAtField; use Shopware\Core\Framework\DataAbstractionLayer\Field\FkField; use Shopware\Core\Framework\DataAbstractionLayer\Field\Flag\PrimaryKey; use Shopware\Core\Framework\DataAbstractionLayer\Field\Flag\Required; use Shopware\Core\Framework\DataAbstractionLayer\Field\IdField; use Shopware\Core\Framework\DataAbstractionLayer\Field\JsonField; -use Shopware\Core\Framework\DataAbstractionLayer\Field\LongTextField; use Shopware\Core\Framework\DataAbstractionLayer\Field\ManyToOneAssociationField; use Shopware\Core\Framework\DataAbstractionLayer\Field\StringField; use Shopware\Core\Framework\DataAbstractionLayer\Field\UpdatedAtField; @@ -47,20 +47,24 @@ protected function defineFields(): FieldCollection { return new FieldCollection([ (new IdField('id', 'id'))->addFlags(new PrimaryKey(), new Required()), + new FkField('run_id', 'runId', SwagMigrationRunDefinition::class), + (new StringField('profile_name', 'profileName', 64))->addFlags(new Required()), + (new StringField('gateway_name', 'gatewayName', 64))->addFlags(new Required()), (new StringField('level', 'level', 64))->addFlags(new Required()), (new StringField('code', 'code'))->addFlags(new Required()), - (new LongTextField('title', 'title'))->addFlags(new Required()), - (new LongTextField('description', 'description'))->addFlags(new Required()), - (new JsonField('parameters', 'parameters'))->addFlags(new Required()), - (new StringField('title_snippet', 'titleSnippet'))->addFlags(new Required()), - (new StringField('description_snippet', 'descriptionSnippet'))->addFlags(new Required()), - new StringField('entity', 'entity'), - new StringField('source_id', 'sourceId'), - new FkField('run_id', 'runId', SwagMigrationRunDefinition::class), + (new BoolField('user_fixable', 'userFixable'))->addFlags(new Required()), + new StringField('entity_name', 'entityName', 64), + new StringField('field_name', 'fieldName', 64), + new StringField('field_source_path', 'fieldSourcePath', 255), + new JsonField('source_data', 'sourceData'), + new JsonField('converted_data', 'convertedData'), + new StringField('exception_message', 'exceptionMessage', 255), + new JsonField('exception_trace', 'exceptionTrace'), + new IdField('entity_id', 'entityId'), + new AutoIncrementField(), new CreatedAtField(), new UpdatedAtField(), new ManyToOneAssociationField('run', 'run_id', SwagMigrationRunDefinition::class), - new AutoIncrementField(), ]); } } diff --git a/src/Migration/Logging/SwagMigrationLoggingEntity.php b/src/Migration/Logging/SwagMigrationLoggingEntity.php index 56727b665..f26a732c9 100644 --- a/src/Migration/Logging/SwagMigrationLoggingEntity.php +++ b/src/Migration/Logging/SwagMigrationLoggingEntity.php @@ -17,29 +17,86 @@ class SwagMigrationLoggingEntity extends Entity { use EntityIdTrait; + protected string $runId; + + protected ?SwagMigrationRunEntity $run = null; + + protected string $profileName; + + protected string $gatewayName; + protected string $level; protected string $code; - protected string $title; + protected bool $userFixable; - protected string $description; + protected int $autoIncrement; - protected array $parameters; + protected ?string $entityName = null; - protected string $titleSnippet; + protected ?string $fieldName = null; - protected string $descriptionSnippet; + protected ?string $fieldSourcePath = null; - protected ?string $entity; + /** + * @var array>|null + */ + protected ?array $sourceData = null; - protected ?string $sourceId; + /** + * @var array>|null + */ + protected ?array $convertedData = null; - protected ?string $runId; + protected ?string $exceptionMessage = null; - protected ?SwagMigrationRunEntity $run; + protected ?string $entityId; - protected int $autoIncrement; + /** + * @var array>|null + */ + protected ?array $exceptionTrace = null; + + public function getRunId(): string + { + return $this->runId; + } + + public function setRunId(string $runId): void + { + $this->runId = $runId; + } + + public function getRun(): ?SwagMigrationRunEntity + { + return $this->run; + } + + public function setRun(SwagMigrationRunEntity $run): void + { + $this->run = $run; + } + + public function getProfileName(): string + { + return $this->profileName; + } + + public function setProfileName(string $profileName): void + { + $this->profileName = $profileName; + } + + public function getGatewayName(): string + { + return $this->gatewayName; + } + + public function setGatewayName(string $gatewayName): void + { + $this->gatewayName = $gatewayName; + } public function getLevel(): string { @@ -61,103 +118,121 @@ public function setCode(string $code): void $this->code = $code; } - public function getTitle(): string + public function isUserFixable(): bool { - return $this->title; + return $this->userFixable; } - public function setTitle(string $title): void + public function setUserFixable(bool $userFixable): void { - $this->title = $title; + $this->userFixable = $userFixable; } - public function getDescription(): string + public function getAutoIncrement(): int { - return $this->description; + return $this->autoIncrement; } - public function setDescription(string $description): void + public function setAutoIncrement(int $autoIncrement): void { - $this->description = $description; + $this->autoIncrement = $autoIncrement; } - public function getParameters(): array + public function getEntityName(): ?string { - return $this->parameters; + return $this->entityName; } - public function setParameters(array $parameters): void + public function setEntityName(string $entityName): void { - $this->parameters = $parameters; + $this->entityName = $entityName; } - public function getTitleSnippet(): string + public function getFieldName(): ?string { - return $this->titleSnippet; + return $this->fieldName; } - public function setTitleSnippet(string $titleSnippet): void + public function setFieldName(string $fieldName): void { - $this->titleSnippet = $titleSnippet; + $this->fieldName = $fieldName; } - public function getDescriptionSnippet(): string + public function getFieldSourcePath(): ?string { - return $this->descriptionSnippet; + return $this->fieldSourcePath; } - public function setDescriptionSnippet(string $descriptionSnippet): void + public function setFieldSourcePath(string $fieldSourcePath): void { - $this->descriptionSnippet = $descriptionSnippet; + $this->fieldSourcePath = $fieldSourcePath; } - public function getEntity(): ?string + /** + * @return array>|null + */ + public function getSourceData(): ?array { - return $this->entity; + return $this->sourceData; } - public function setEntity(?string $entity): void + /** + * @param array> $sourceData + */ + public function setSourceData(array $sourceData): void { - $this->entity = $entity; + $this->sourceData = $sourceData; } - public function getSourceId(): ?string + /** + * @return array>|null + */ + public function getConvertedData(): ?array { - return $this->sourceId; + return $this->convertedData; } - public function setSourceId(?string $sourceId): void + /** + * @param array> $convertedData + */ + public function setConvertedData(array $convertedData): void { - $this->sourceId = $sourceId; + $this->convertedData = $convertedData; } - public function getRunId(): ?string + public function getExceptionMessage(): ?string { - return $this->runId; + return $this->exceptionMessage; } - public function setRunId(?string $runId): void + public function setExceptionMessage(string $exceptionMessage): void { - $this->runId = $runId; + $this->exceptionMessage = $exceptionMessage; } - public function getRun(): ?SwagMigrationRunEntity + /** + * @return array>|null + */ + public function getExceptionTrace(): ?array { - return $this->run; + return $this->exceptionTrace; } - public function setRun(?SwagMigrationRunEntity $run): void + /** + * @param array> $exceptionTrace + */ + public function setExceptionTrace(array $exceptionTrace): void { - $this->run = $run; + $this->exceptionTrace = $exceptionTrace; } - public function getAutoIncrement(): int + public function getEntityId(): ?string { - return $this->autoIncrement; + return $this->entityId; } - public function setAutoIncrement(int $autoIncrement): void + public function setEntityId(?string $entityId): void { - $this->autoIncrement = $autoIncrement; + $this->entityId = $entityId; } } diff --git a/src/Migration/Mapping/Lookup/LanguageLookup.php b/src/Migration/Mapping/Lookup/LanguageLookup.php index 248b072ef..4204c422a 100644 --- a/src/Migration/Mapping/Lookup/LanguageLookup.php +++ b/src/Migration/Mapping/Lookup/LanguageLookup.php @@ -52,7 +52,7 @@ public function get(string $localeCode, Context $context): ?string $localeUuid = $this->localeLookup->get($localeCode, $context); if ($localeUuid === null) { - throw MigrationException::localeForLanguageLookupNotFound($localeCode); + throw MigrationException::localeNotFound($localeCode); } $language = $this->getLanguage($localeUuid, $context); diff --git a/src/Migration/Mapping/MappingService.php b/src/Migration/Mapping/MappingService.php index 3afb1a88c..d84ab7b04 100644 --- a/src/Migration/Mapping/MappingService.php +++ b/src/Migration/Mapping/MappingService.php @@ -17,6 +17,8 @@ use Shopware\Core\Framework\DataAbstractionLayer\Search\EntitySearchResult; use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsAnyFilter; use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsFilter; +use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\MultiFilter; +use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\NotFilter; use Shopware\Core\Framework\DataAbstractionLayer\Write\EntityWriterInterface; use Shopware\Core\Framework\Log\Package; use Shopware\Core\Framework\Uuid\Uuid; @@ -85,7 +87,7 @@ public function getOrCreateMapping( } if ($uuid !== null) { - $mapping['entityUuid'] = $uuid; + $mapping['entityId'] = $uuid; } if ($entityValue !== null) { @@ -118,7 +120,7 @@ public function getMapping( connection_id AS connectionId, entity, old_identifier AS oldIdentifier, - entity_uuid AS entityUuid, + entity_id AS entityId, entity_value AS entityValue, checksum, additional_data AS additionalData @@ -133,7 +135,7 @@ public function getMapping( $mapping['id'] = Uuid::fromBytesToHex($mapping['id']); $mapping['connectionId'] = Uuid::fromBytesToHex($mapping['connectionId']); - $mapping['entityUuid'] = $mapping['entityUuid'] === null ? null : Uuid::fromBytesToHex($mapping['entityUuid']); + $mapping['entityId'] = $mapping['entityId'] === null ? null : Uuid::fromBytesToHex($mapping['entityId']); if (!empty($mapping['additionalData'])) { $mapping['additionalData'] = \json_decode($mapping['additionalData'], true, 512, \JSON_THROW_ON_ERROR); } else { @@ -159,14 +161,14 @@ public function createMapping( ?string $uuid = null, ?string $entityValue = null, ): array { - $fallbackEntityUuid = $entityValue !== null ? null : Uuid::randomHex(); + $fallbackEntityId = $entityValue !== null ? null : Uuid::randomHex(); $mapping = [ 'id' => Uuid::randomHex(), 'connectionId' => $connectionId, 'entity' => $entityName, 'oldIdentifier' => $oldIdentifier, - 'entityUuid' => $uuid ?? $fallbackEntityUuid, + 'entityId' => $uuid ?? $fallbackEntityId, 'entityValue' => $entityValue, 'checksum' => $checksum, 'additionalData' => $additionalData, @@ -192,7 +194,7 @@ public function updateMapping( $oldIdentifier, $updateData['checksum'] ?? null, $updateData['additionalData'] ?? null, - $updateData['entityUuid'] ?? null + $updateData['entityId'] ?? null ); } @@ -212,6 +214,22 @@ public function getMappings(string $connectionId, string $entityName, array $ids return $this->migrationMappingRepo->search($criteria, $context); } + public function hasValidMappingByEntityId(string $connectionId, string $entityName, string $entityId, Context $context): bool + { + $criteria = new Criteria(); + $criteria->addFilter( + new EqualsFilter('connectionId', $connectionId), + new EqualsFilter('entity', $entityName), + new EqualsFilter('entityId', $entityId), + new NotFilter(MultiFilter::CONNECTION_AND, [ + new EqualsFilter('oldIdentifier', null), + ]), + ); + $criteria->setLimit(1); + + return $this->migrationMappingRepo->searchIds($criteria, $context)->getTotal() > 0; + } + public function preloadMappings(array $mappingIds, Context $context): void { if (empty($mappingIds)) { @@ -230,7 +248,7 @@ public function preloadMappings(array $mappingIds, Context $context): void 'connectionId' => $mapping->getConnectionId(), 'entity' => $entityName, 'oldIdentifier' => $oldIdentifier, - 'entityUuid' => $mapping->getEntityUuid(), + 'entityId' => $mapping->getEntityId(), 'entityValue' => $mapping->getEntityValue(), 'checksum' => $mapping->getChecksum(), 'additionalData' => $mapping->getAdditionalData(), @@ -248,12 +266,12 @@ public function getUuidsByEntity(string $connectionId, string $entityName, Conte $entities = $this->migrationMappingRepo->search($criteria, $context)->getEntities(); - $entityUuids = []; + $entityIds = []; foreach ($entities as $entity) { - $entityUuids[] = $entity->getEntityUuid(); + $entityIds[] = $entity->getEntityId(); } - return $entityUuids; + return $entityIds; } public function getValue(string $connectionId, string $entityName, string $oldIdentifier, Context $context): ?string @@ -285,7 +303,7 @@ public function getValue(string $connectionId, string $entityName, string $oldId 'connectionId' => $element->getConnectionId(), 'entity' => $element->getEntity(), 'oldIdentifier' => $element->getOldIdentifier(), - 'entityUuid' => $element->getEntityUuid(), + 'entityId' => $element->getEntityId(), 'entityValue' => $value, 'checksum' => $element->getChecksum(), 'additionalData' => $element->getAdditionalData(), @@ -298,10 +316,10 @@ public function getValue(string $connectionId, string $entityName, string $oldId return null; } - public function deleteMapping(string $entityUuid, string $connectionId, Context $context): void + public function deleteMapping(string $entityId, string $connectionId, Context $context): void { foreach ($this->writeArray as $key => $writeMapping) { - if ($writeMapping['connectionId'] === $connectionId && $writeMapping['entityUuid'] === $entityUuid) { + if ($writeMapping['connectionId'] === $connectionId && $writeMapping['entityId'] === $entityId) { unset($this->writeArray[$key]); $this->writeArray = \array_values($this->writeArray); @@ -310,13 +328,13 @@ public function deleteMapping(string $entityUuid, string $connectionId, Context } foreach ($this->mappings as $hash => $mapping) { - if (isset($mapping['entityUuid']) && $mapping['entityUuid'] === $entityUuid) { + if (isset($mapping['entityId']) && $mapping['entityId'] === $entityId) { unset($this->mappings[$hash]); } } $criteria = new Criteria(); - $criteria->addFilter(new EqualsFilter('entityUuid', $entityUuid)); + $criteria->addFilter(new EqualsFilter('entityId', $entityId)); $criteria->addFilter(new EqualsFilter('connectionId', $connectionId)); $criteria->setLimit(1); @@ -335,12 +353,12 @@ public function writeMapping(): void try { $isFirstInsert = true; - $insertSql = 'INSERT INTO swag_migration_mapping (id, connection_id, entity, old_identifier, entity_uuid, entity_value, checksum, additional_data, created_at) VALUES '; + $insertSql = 'INSERT INTO swag_migration_mapping (id, connection_id, entity, old_identifier, entity_id, entity_value, checksum, additional_data, created_at) VALUES '; $insertParams = []; $updateSql = ' ON DUPLICATE KEY UPDATE entity = VALUES(entity), old_identifier = VALUES(old_identifier), - entity_uuid = VALUES(entity_uuid), + entity_id = VALUES(entity_id), entity_value = VALUES(entity_value), checksum = VALUES(checksum), additional_data = VALUES(additional_data), @@ -352,13 +370,13 @@ public function writeMapping(): void $insertSql .= ', '; } - $insertSql .= \sprintf('(:id%d, :connectionId%d, :entity%d, :oldIdentifier%d, :entityUuid%d, :entityValue%d, :checksum%d, :additionalData%d, :createdAt%d)', $index, $index, $index, $index, $index, $index, $index, $index, $index); + $insertSql .= \sprintf('(:id%d, :connectionId%d, :entity%d, :oldIdentifier%d, :entityId%d, :entityValue%d, :checksum%d, :additionalData%d, :createdAt%d)', $index, $index, $index, $index, $index, $index, $index, $index, $index); $insertParams['id' . $index] = Uuid::fromHexToBytes($writeMapping['id']); $insertParams['connectionId' . $index] = Uuid::fromHexToBytes($writeMapping['connectionId']); $insertParams['entity' . $index] = $writeMapping['entity']; $insertParams['oldIdentifier' . $index] = $writeMapping['oldIdentifier']; - $insertParams['entityUuid' . $index] = $writeMapping['entityUuid'] === null ? null : Uuid::fromHexToBytes($writeMapping['entityUuid']); + $insertParams['entityId' . $index] = $writeMapping['entityId'] === null ? null : Uuid::fromHexToBytes($writeMapping['entityId']); $insertParams['entityValue' . $index] = $writeMapping['entityValue']; $insertParams['checksum' . $index] = $writeMapping['checksum']; $insertParams['additionalData' . $index] = \json_encode($writeMapping['additionalData']); @@ -390,7 +408,7 @@ public function getMigratedSalesChannelUuids(string $connectionId, Context $cont $uuids = []; foreach ($result as $swagMigrationMappingEntity) { - $uuid = $swagMigrationMappingEntity->getEntityUuid(); + $uuid = $swagMigrationMappingEntity->getEntityId(); if ($uuid === null) { continue; @@ -423,12 +441,12 @@ private function writePerEntry(): void { foreach ($this->writeArray as $mapping) { try { - $insertSql = 'INSERT INTO swag_migration_mapping (id, connection_id, entity, old_identifier, entity_uuid, entity_value, checksum, additional_data, created_at) - VALUES (:id, :connectionId, :entity, :oldIdentifier, :entityUuid, :entityValue, :checksum, :additionalData, :createdAt) + $insertSql = 'INSERT INTO swag_migration_mapping (id, connection_id, entity, old_identifier, entity_id, entity_value, checksum, additional_data, created_at) + VALUES (:id, :connectionId, :entity, :oldIdentifier, :entityId, :entityValue, :checksum, :additionalData, :createdAt) ON DUPLICATE KEY UPDATE entity = VALUES(entity), old_identifier = VALUES(old_identifier), - entity_uuid = VALUES(entity_uuid), + entity_id = VALUES(entity_id), entity_value = VALUES(entity_value), checksum = VALUES(checksum), additional_data = VALUES(additional_data), @@ -439,7 +457,7 @@ private function writePerEntry(): void $insertParams['connectionId'] = Uuid::fromHexToBytes($mapping['connectionId']); $insertParams['entity'] = $mapping['entity']; $insertParams['oldIdentifier'] = $mapping['oldIdentifier']; - $insertParams['entityUuid'] = $mapping['entityUuid'] === null ? null : Uuid::fromHexToBytes($mapping['entityUuid']); + $insertParams['entityId'] = $mapping['entityId'] === null ? null : Uuid::fromHexToBytes($mapping['entityId']); $insertParams['entityValue'] = $mapping['entityValue']; $insertParams['checksum'] = $mapping['checksum']; $insertParams['additionalData'] = \json_encode($mapping['additionalData']); diff --git a/src/Migration/Mapping/MappingServiceInterface.php b/src/Migration/Mapping/MappingServiceInterface.php index 200769f5a..20dd09660 100644 --- a/src/Migration/Mapping/MappingServiceInterface.php +++ b/src/Migration/Mapping/MappingServiceInterface.php @@ -12,7 +12,7 @@ use Shopware\Core\Framework\Log\Package; /** - * @phpstan-type MappingStruct array{id: string, connectionId: string, oldIdentifier: ?string, entityUuid: ?string, entityValue: ?string, checksum: ?string, additionalData: ?array} + * @phpstan-type MappingStruct array{id: string, connectionId: string, oldIdentifier: ?string, entityId: ?string, entityValue: ?string, checksum: ?string, additionalData: ?array} */ #[Package('fundamentals@after-sales')] interface MappingServiceInterface @@ -75,7 +75,7 @@ public function updateMapping( */ public function getMigratedSalesChannelUuids(string $connectionId, Context $context): array; - public function deleteMapping(string $entityUuid, string $connectionId, Context $context): void; + public function deleteMapping(string $entityId, string $connectionId, Context $context): void; public function writeMapping(): void; @@ -84,5 +84,7 @@ public function writeMapping(): void; */ public function getMappings(string $connectionId, string $entityName, array $ids, Context $context): EntitySearchResult; + public function hasValidMappingByEntityId(string $connectionId, string $entityName, string $entityId, Context $context): bool; + public function preloadMappings(array $mappingIds, Context $context): void; } diff --git a/src/Migration/Mapping/SwagMigrationMappingDefinition.php b/src/Migration/Mapping/SwagMigrationMappingDefinition.php index dd93e6330..3a52470c2 100644 --- a/src/Migration/Mapping/SwagMigrationMappingDefinition.php +++ b/src/Migration/Mapping/SwagMigrationMappingDefinition.php @@ -38,7 +38,7 @@ public function defineFields(): FieldCollection (new FkField('connection_id', 'connectionId', SwagMigrationConnectionDefinition::class))->addFlags(new Required()), (new StringField('entity', 'entity'))->addFlags(new Required()), new StringField('old_identifier', 'oldIdentifier'), - new IdField('entity_uuid', 'entityUuid'), + new IdField('entity_id', 'entityId'), new StringField('entity_value', 'entityValue'), new StringField('checksum', 'checksum'), new JsonField('additional_data', 'additionalData'), diff --git a/src/Migration/Mapping/SwagMigrationMappingEntity.php b/src/Migration/Mapping/SwagMigrationMappingEntity.php index 37871f5ec..284487165 100644 --- a/src/Migration/Mapping/SwagMigrationMappingEntity.php +++ b/src/Migration/Mapping/SwagMigrationMappingEntity.php @@ -25,7 +25,7 @@ class SwagMigrationMappingEntity extends Entity protected ?string $oldIdentifier; - protected ?string $entityUuid; + protected ?string $entityId; protected ?string $entityValue; @@ -76,14 +76,14 @@ public function setOldIdentifier(string $oldIdentifier): void $this->oldIdentifier = $oldIdentifier; } - public function getEntityUuid(): ?string + public function getEntityId(): ?string { - return $this->entityUuid; + return $this->entityId; } - public function setEntityUuid(string $entityUuid): void + public function setEntityId(string $entityId): void { - $this->entityUuid = $entityUuid; + $this->entityId = $entityId; } public function getEntityValue(): ?string diff --git a/src/Migration/Media/MediaFileProcessorRegistry.php b/src/Migration/Media/MediaFileProcessorRegistry.php index eb2cd770d..44b431fd2 100644 --- a/src/Migration/Media/MediaFileProcessorRegistry.php +++ b/src/Migration/Media/MediaFileProcessorRegistry.php @@ -9,7 +9,6 @@ use Shopware\Core\Framework\Log\Package; use SwagMigrationAssistant\Exception\MigrationException; -use SwagMigrationAssistant\Migration\Connection\SwagMigrationConnectionEntity; use SwagMigrationAssistant\Migration\MigrationContextInterface; #[Package('fundamentals@after-sales')] @@ -34,10 +33,10 @@ public function getProcessor(MigrationContextInterface $migrationContext): Media } $connection = $migrationContext->getConnection(); - if ($connection === null) { - throw MigrationException::entityNotExists(SwagMigrationConnectionEntity::class, $migrationContext->getRunUuid()); - } - throw MigrationException::processorNotFound($connection->getProfileName(), $connection->getGatewayName()); + throw MigrationException::processorNotFound( + $connection->getProfileName(), + $connection->getGatewayName() + ); } } diff --git a/src/Migration/Media/Processor/HttpDownloadServiceBase.php b/src/Migration/Media/Processor/HttpDownloadServiceBase.php index 2f02e92d6..224858cf7 100644 --- a/src/Migration/Media/Processor/HttpDownloadServiceBase.php +++ b/src/Migration/Media/Processor/HttpDownloadServiceBase.php @@ -9,20 +9,22 @@ use Doctrine\DBAL\Connection; use GuzzleHttp\Exception\RequestException; -use GuzzleHttp\Promise; use GuzzleHttp\Promise\PromiseInterface; use GuzzleHttp\Promise\Utils; use Psr\Http\Message\ResponseInterface; use Shopware\Core\Content\Media\File\FileSaver; use Shopware\Core\Content\Media\File\MediaFile; +use Shopware\Core\Content\Media\MediaDefinition; use Shopware\Core\Content\Media\MediaException; use Shopware\Core\Framework\Context; use Shopware\Core\Framework\DataAbstractionLayer\EntityRepository; use Shopware\Core\Framework\DataAbstractionLayer\Exception\InconsistentCriteriaIdsException; use Shopware\Core\Framework\Log\Package; +use Shopware\Core\Framework\Util\Hasher; use Shopware\Core\Framework\Uuid\Uuid; use SwagMigrationAssistant\Exception\MigrationException; use SwagMigrationAssistant\Migration\Gateway\HttpClientInterface; +use SwagMigrationAssistant\Migration\Logging\Log\Builder\MigrationLogBuilder; use SwagMigrationAssistant\Migration\Logging\Log\CannotGetFileRunLog; use SwagMigrationAssistant\Migration\Logging\Log\ExceptionRunLog; use SwagMigrationAssistant\Migration\Logging\Log\TemporaryFileErrorLog; @@ -74,17 +76,21 @@ public function process(MigrationContextInterface $migrationContext, Context $co // prepare http client $client = $this->getHttpClient($migrationContext); if ($client === null) { - $this->loggingService->addLogEntry(new ExceptionRunLog( - $migrationContext->getRunUuid(), - $this->getMediaEntity(), - new \Exception('Http download client can not be constructed.') - )); + $exception = new \Exception('Http download client can not be constructed.'); + + $this->loggingService->addLogEntry( + MigrationLogBuilder::fromMigrationContext($migrationContext) + ->withExceptionMessage($exception->getMessage()) + ->withExceptionTrace($exception->getTrace()) + ->withEntityName(MediaDefinition::ENTITY_NAME) + ->build(ExceptionRunLog::class) + ); $this->loggingService->saveLogging($context); return $workload; } // Do download requests and store the promises - $promises = $this->doMediaDownloadRequests($media, $mappedWorkload, $client); + $promises = $this->doMediaDownloadRequests($migrationContext, $media, $mappedWorkload, $client); // Wait for the requests to complete, even if some of them fail /** @var array $results */ @@ -117,13 +123,13 @@ function (MediaProcessWorkloadStruct $work) use ($uuid) { if ($work->getErrorCount() > ProcessMediaHandler::MEDIA_ERROR_THRESHOLD) { $failureUuids[] = $uuid; $work->setState(MediaProcessWorkloadStruct::ERROR_STATE); - $this->loggingService->addLogEntry(new CannotGetFileRunLog( - $work->getRunId(), - $this->getMediaEntity(), - $work->getMediaId(), - $work->getAdditionalData()['uri'], - $result['reason'] ?? null - )); + + $this->loggingService->addLogEntry( + MigrationLogBuilder::fromMigrationContext($migrationContext) + ->withEntityName(MediaDefinition::ENTITY_NAME) + ->withEntityId($uuid) + ->build(CannotGetFileRunLog::class) + ); } continue; @@ -138,11 +144,13 @@ function (MediaProcessWorkloadStruct $work) use ($uuid) { if ($filePath === false) { $failureUuids[] = $uuid; $work->setState(MediaProcessWorkloadStruct::ERROR_STATE); - $this->loggingService->addLogEntry(new TemporaryFileErrorLog( - $work->getRunId(), - $this->getMediaEntity(), - $uuid - )); + + $this->loggingService->addLogEntry( + MigrationLogBuilder::fromMigrationContext($migrationContext) + ->withEntityName(MediaDefinition::ENTITY_NAME) + ->withEntityId($uuid) + ->build(TemporaryFileErrorLog::class) + ); continue; } @@ -179,12 +187,14 @@ function (MediaProcessWorkloadStruct $work) use ($uuid) { } catch (\Exception $e) { $failureUuids[] = $uuid; $work->setState(MediaProcessWorkloadStruct::ERROR_STATE); - $this->loggingService->addLogEntry(new ExceptionRunLog( - $work->getRunId(), - $this->getMediaEntity(), - $e, - $uuid - )); + $this->loggingService->addLogEntry( + MigrationLogBuilder::fromMigrationContext($migrationContext) + ->withExceptionMessage($e->getMessage()) + ->withExceptionTrace($e->getTrace()) + ->withEntityName(MediaDefinition::ENTITY_NAME) + ->withEntityId($uuid) + ->build(ExceptionRunLog::class) + ); } finally { // clear up temp data \unlink($filePath); @@ -246,7 +256,7 @@ final protected function getDataSetEntity(MigrationContextInterface $migrationCo * * @return array */ - private function doMediaDownloadRequests(array $media, array &$mappedWorkload, HttpClientInterface $client): array + private function doMediaDownloadRequests(MigrationContextInterface $migrationContext, array $media, array &$mappedWorkload, HttpClientInterface $client): array { $promises = []; foreach ($media as $mediaFile) { @@ -256,7 +266,7 @@ private function doMediaDownloadRequests(array $media, array &$mappedWorkload, H $additionalData['uri'] = $mediaFile['uri']; $mappedWorkload[$uuid]->setAdditionalData($additionalData); - $promise = $this->doNormalDownloadRequest($mappedWorkload[$uuid], $client); + $promise = $this->doNormalDownloadRequest($migrationContext, $mappedWorkload[$uuid], $client); if ($promise !== null) { $promises[$uuid] = $promise; @@ -266,7 +276,7 @@ private function doMediaDownloadRequests(array $media, array &$mappedWorkload, H return $promises; } - private function doNormalDownloadRequest(MediaProcessWorkloadStruct $workload, HttpClientInterface $client): ?PromiseInterface + private function doNormalDownloadRequest(MigrationContextInterface $migrationContext, MediaProcessWorkloadStruct $workload, HttpClientInterface $client): ?PromiseInterface { $additionalData = $workload->getAdditionalData(); @@ -277,12 +287,13 @@ private function doNormalDownloadRequest(MediaProcessWorkloadStruct $workload, H $workload->setState(MediaProcessWorkloadStruct::FINISH_STATE); } catch (\Throwable $exception) { // this should never happen because of Promises, but just in case something is wrong with request construction - $this->loggingService->addLogEntry(new ExceptionRunLog( - $workload->getRunId(), - $this->getMediaEntity(), - $exception, - $workload->getMediaId() - )); + $this->loggingService->addLogEntry( + MigrationLogBuilder::fromMigrationContext($migrationContext) + ->withExceptionMessage($exception->getMessage()) + ->withExceptionTrace($exception->getTrace()) + ->withEntityName(MediaDefinition::ENTITY_NAME) + ->build(ExceptionRunLog::class) + ); $promise = null; $workload->setErrorCount($workload->getErrorCount() + 1); @@ -296,23 +307,28 @@ private function persistFileToMedia(string $filePath, string $uuid, string $name // determine correct info about the temporary file, except for the $fileExtension (which can be overridden) $fileSize = \filesize($filePath); $mimeType = \mime_content_type($filePath); + if ($fileSize === false || $fileSize === 0 || $mimeType === false) { - $this->loggingService->addLogEntry(new ExceptionRunLog( - $migrationContext->getRunUuid(), - $this->getMediaEntity(), - new \Exception('Downloaded file is empty or could not determine mime type.'), - $uuid - )); + $exception = new \Exception('Downloaded file is empty or could not determine mime type.'); + + $this->loggingService->addLogEntry( + MigrationLogBuilder::fromMigrationContext($migrationContext) + ->withExceptionMessage($exception->getMessage()) + ->withExceptionTrace($exception->getTrace()) + ->withEntityName(MediaDefinition::ENTITY_NAME) + ->build(ExceptionRunLog::class) + ); return; } - $fileHash = \hash_file('md5', $filePath); + + $fileHash = Hasher::hashFile($filePath); $mediaFile = new MediaFile( $filePath, $mimeType, $fileExtension, $fileSize, - $fileHash === false ? null : $fileHash + $fileHash ); $name = \preg_replace('/[^a-zA-Z0-9_-]+/', '-', \mb_strtolower($name)) ?? $uuid; @@ -331,12 +347,13 @@ private function persistFileToMedia(string $filePath, string $uuid, string $name } elseif (\in_array($mediaException->getErrorCode(), [MediaException::MEDIA_ILLEGAL_FILE_NAME, MediaException::MEDIA_EMPTY_FILE_NAME], true)) { $this->fileSaver->persistFileToMedia($mediaFile, Uuid::randomHex(), $uuid, $context); } else { - $this->loggingService->addLogEntry(new ExceptionRunLog( - $migrationContext->getRunUuid(), - $this->getMediaEntity(), - $mediaException, - $uuid - )); + $this->loggingService->addLogEntry( + MigrationLogBuilder::fromMigrationContext($migrationContext) + ->withExceptionMessage($mediaException->getMessage()) + ->withExceptionTrace($mediaException->getTrace()) + ->withEntityName(MediaDefinition::ENTITY_NAME) + ->build(ExceptionRunLog::class) + ); } } }); diff --git a/src/Migration/MessageQueue/Handler/MigrationProcessHandler.php b/src/Migration/MessageQueue/Handler/MigrationProcessHandler.php index e6d37f8a5..a3ae98e5d 100644 --- a/src/Migration/MessageQueue/Handler/MigrationProcessHandler.php +++ b/src/Migration/MessageQueue/Handler/MigrationProcessHandler.php @@ -54,7 +54,7 @@ public function __invoke(MigrationProcessMessage $message): void } $processor = $this->processorRegistry->getProcessor($run->getStep()); - $processor->process($migrationContext, $context, $run, $progress); + $processor?->process($migrationContext, $context, $run, $progress); } private function getCurrentRun(MigrationProcessMessage $message, Context $context): SwagMigrationRunEntity @@ -62,7 +62,7 @@ private function getCurrentRun(MigrationProcessMessage $message, Context $contex $run = $this->migrationRunRepo->search(new Criteria([$message->getRunUuid()]), $context)->getEntities()->first(); if ($run === null) { - throw MigrationException::noRunningMigration($message->getRunUuid()); + throw MigrationException::runNotFound($message->getRunUuid()); } return $run; diff --git a/src/Migration/MessageQueue/Handler/MigrationProcessorRegistry.php b/src/Migration/MessageQueue/Handler/MigrationProcessorRegistry.php index 2c11cdcf5..9d70c74c3 100644 --- a/src/Migration/MessageQueue/Handler/MigrationProcessorRegistry.php +++ b/src/Migration/MessageQueue/Handler/MigrationProcessorRegistry.php @@ -25,8 +25,12 @@ public function __construct(private readonly iterable $processors) { } - public function getProcessor(MigrationStep $step): MigrationProcessorInterface + public function getProcessor(MigrationStep $step): ?MigrationProcessorInterface { + if (!$step->needsProcessor()) { + return null; + } + foreach ($this->processors as $processor) { if ($processor->supports($step)) { return $processor; diff --git a/src/Migration/MessageQueue/Handler/ProcessMediaHandler.php b/src/Migration/MessageQueue/Handler/ProcessMediaHandler.php index 6839764c6..6c8f8d366 100644 --- a/src/Migration/MessageQueue/Handler/ProcessMediaHandler.php +++ b/src/Migration/MessageQueue/Handler/ProcessMediaHandler.php @@ -7,12 +7,13 @@ namespace SwagMigrationAssistant\Migration\MessageQueue\Handler; +use Shopware\Core\Content\Media\MediaDefinition; use Shopware\Core\Framework\Context; use Shopware\Core\Framework\DataAbstractionLayer\EntityRepository; use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria; use Shopware\Core\Framework\Log\Package; use SwagMigrationAssistant\Exception\MigrationException; -use SwagMigrationAssistant\Exception\NoConnectionFoundException; +use SwagMigrationAssistant\Migration\Logging\Log\Builder\MigrationLogBuilder; use SwagMigrationAssistant\Migration\Logging\Log\ExceptionRunLog; use SwagMigrationAssistant\Migration\Logging\Log\ProcessorNotFoundLog; use SwagMigrationAssistant\Migration\Logging\LoggingServiceInterface; @@ -81,23 +82,30 @@ public function __invoke(ProcessMediaMessage $message): void try { $processor = $this->mediaFileProcessorRegistry->getProcessor($migrationContext); - $workload = $processor->process($migrationContext, $context, $workload); - $this->processFailures($context, $migrationContext, $processor, $workload); - } catch (NoConnectionFoundException $e) { - $this->loggingService->addLogEntry(new ProcessorNotFoundLog( - $message->getRunId(), - $message->getEntityName(), - $connection->getProfileName(), - $connection->getGatewayName() - )); + } catch (MigrationException $exception) { + $this->loggingService->addLogEntry( + MigrationLogBuilder::fromMigrationContext($migrationContext) + ->withExceptionMessage($exception->getMessage()) + ->withEntityName(MediaDefinition::ENTITY_NAME) + ->build(ProcessorNotFoundLog::class) + ); $this->loggingService->saveLogging($context); - } catch (\Exception $e) { - $this->loggingService->addLogEntry(new ExceptionRunLog( - $message->getRunId(), - $message->getEntityName(), - $e - )); + + return; + } + + try { + $workload = $processor->process($migrationContext, $context, $workload); + $this->processFailures($context, $migrationContext, $processor, $workload); + } catch (\Exception $exception) { + $this->loggingService->addLogEntry( + MigrationLogBuilder::fromMigrationContext($migrationContext) + ->withExceptionMessage($exception->getMessage()) + ->withExceptionTrace($exception->getTrace()) + ->withEntityName(MediaDefinition::ENTITY_NAME) + ->build(ExceptionRunLog::class) + ); $this->loggingService->saveLogging($context); } diff --git a/src/Migration/MessageQueue/Handler/Processor/AbortingProcessor.php b/src/Migration/MessageQueue/Handler/Processor/AbortingProcessor.php index 467a4c490..011df47bf 100644 --- a/src/Migration/MessageQueue/Handler/Processor/AbortingProcessor.php +++ b/src/Migration/MessageQueue/Handler/Processor/AbortingProcessor.php @@ -10,14 +10,12 @@ use Shopware\Core\Framework\Context; use Shopware\Core\Framework\DataAbstractionLayer\EntityRepository; use Shopware\Core\Framework\Log\Package; -use SwagMigrationAssistant\Exception\MigrationException; use SwagMigrationAssistant\Migration\Data\SwagMigrationDataCollection; use SwagMigrationAssistant\Migration\Media\SwagMigrationMediaFileCollection; -use SwagMigrationAssistant\Migration\MessageQueue\Message\MigrationProcessMessage; +use SwagMigrationAssistant\Migration\MessageQueue\Message\ResetChecksumMessage; use SwagMigrationAssistant\Migration\MigrationContextInterface; use SwagMigrationAssistant\Migration\Run\MigrationProgress; use SwagMigrationAssistant\Migration\Run\MigrationStep; -use SwagMigrationAssistant\Migration\Run\RunServiceInterface; use SwagMigrationAssistant\Migration\Run\RunTransitionServiceInterface; use SwagMigrationAssistant\Migration\Run\SwagMigrationRunCollection; use SwagMigrationAssistant\Migration\Run\SwagMigrationRunEntity; @@ -36,7 +34,6 @@ public function __construct( EntityRepository $migrationDataRepo, EntityRepository $migrationMediaFileRepo, RunTransitionServiceInterface $runTransitionService, - private readonly RunServiceInterface $runService, private readonly MessageBusInterface $bus, ) { parent::__construct( @@ -58,16 +55,14 @@ public function process( SwagMigrationRunEntity $run, MigrationProgress $progress, ): void { - $connection = $migrationContext->getConnection(); - if ($connection === null) { - throw MigrationException::noConnectionFound(); - } - - $this->runService->cleanupMappingChecksums($connection->getId(), $context); - - $this->runTransitionService->forceTransitionToRunStep($migrationContext->getRunUuid(), MigrationStep::CLEANUP); - $progress->setIsAborted(true); - $this->updateProgress($migrationContext->getRunUuid(), $progress, $context); - $this->bus->dispatch(new MigrationProcessMessage($context, $migrationContext->getRunUuid())); + $this->bus->dispatch(new ResetChecksumMessage( + $migrationContext->getConnection()->getId(), + $context, + $run->getId(), + $progress->getCurrentEntity(), + null, + 0, + true // abort flow flag + )); } } diff --git a/src/Migration/MessageQueue/Handler/Processor/AbstractProcessor.php b/src/Migration/MessageQueue/Handler/Processor/AbstractProcessor.php index 6428aef77..837402c2f 100644 --- a/src/Migration/MessageQueue/Handler/Processor/AbstractProcessor.php +++ b/src/Migration/MessageQueue/Handler/Processor/AbstractProcessor.php @@ -63,7 +63,7 @@ protected function changeProgressToNextEntity(SwagMigrationRunEntity $run, Migra if ($nextEntity === null && $run->getStep() === MigrationStep::FETCHING) { $nextEntity = \current($dataSets); - $this->runTransitionService->transitionToRunStep($run->getId(), MigrationStep::WRITING); + $this->runTransitionService->transitionToRunStep($run->getId(), MigrationStep::ERROR_RESOLUTION); $progress->setProgress(0); $progress->setTotal($this->getWriteTotal($context)); } elseif ($nextEntity === null && $run->getStep() === MigrationStep::WRITING) { diff --git a/src/Migration/MessageQueue/Handler/Processor/CleanUpProcessor.php b/src/Migration/MessageQueue/Handler/Processor/CleanUpProcessor.php index 5ebe6ac0e..f6c186d0f 100644 --- a/src/Migration/MessageQueue/Handler/Processor/CleanUpProcessor.php +++ b/src/Migration/MessageQueue/Handler/Processor/CleanUpProcessor.php @@ -9,11 +9,9 @@ use Doctrine\DBAL\Connection; use Shopware\Core\Framework\Context; -use Shopware\Core\Framework\DataAbstractionLayer\Dbal\QueryBuilder; use Shopware\Core\Framework\DataAbstractionLayer\EntityRepository; use Shopware\Core\Framework\Log\Package; use SwagMigrationAssistant\Migration\Data\SwagMigrationDataCollection; -use SwagMigrationAssistant\Migration\Data\SwagMigrationDataDefinition; use SwagMigrationAssistant\Migration\Media\SwagMigrationMediaFileCollection; use SwagMigrationAssistant\Migration\MessageQueue\Message\MigrationProcessMessage; use SwagMigrationAssistant\Migration\MigrationContextInterface; @@ -27,6 +25,8 @@ #[Package('fundamentals@after-sales')] class CleanUpProcessor extends AbstractProcessor { + public const BATCH_SIZE = 250; + /** * @param EntityRepository $migrationRunRepo * @param EntityRepository $migrationDataRepo @@ -37,7 +37,7 @@ public function __construct( EntityRepository $migrationDataRepo, EntityRepository $migrationMediaFileRepo, RunTransitionServiceInterface $runTransitionService, - private readonly Connection $dbalConnection, + private readonly Connection $connection, private readonly MessageBusInterface $bus, ) { parent::__construct( @@ -59,22 +59,51 @@ public function process( SwagMigrationRunEntity $run, MigrationProgress $progress, ): void { - $deleteCount = (int) $this->removeMigrationData(); + if ($progress->getTotal() === 0) { + $progress->setTotal($this->getMigrationDataTotal()); + $progress->setProgress(0); + } + + $deleteCount = $this->removeMigrationData(); + + if ($deleteCount > 0) { + $progress->setProgress( + $progress->getProgress() + $deleteCount + ); + } if ($deleteCount <= 0) { - $this->runTransitionService->transitionToRunStep($migrationContext->getRunUuid(), MigrationStep::INDEXING); + $this->runTransitionService->transitionToRunStep( + $migrationContext->getRunUuid(), + MigrationStep::INDEXING + ); } - $this->updateProgress($migrationContext->getRunUuid(), $progress, $context); - $this->bus->dispatch(new MigrationProcessMessage($context, $migrationContext->getRunUuid())); + $this->updateProgress( + $migrationContext->getRunUuid(), + $progress, + $context + ); + + $this->bus->dispatch(new MigrationProcessMessage( + $context, + $migrationContext->getRunUuid() + )); } - private function removeMigrationData(): int|string + private function removeMigrationData(): int { - return (new QueryBuilder($this->dbalConnection)) - ->delete(SwagMigrationDataDefinition::ENTITY_NAME) - ->andWhere('written = 1') - ->setMaxResults(1000) + return (int) $this->connection->createQueryBuilder() + ->delete('swag_migration_data') + ->setMaxResults(self::BATCH_SIZE) ->executeStatement(); } + + private function getMigrationDataTotal(): int + { + return (int) $this->connection->createQueryBuilder() + ->select('COUNT(id)')->from('swag_migration_data') + ->executeQuery() + ->fetchOne(); + } } diff --git a/src/Migration/MessageQueue/Handler/ResetChecksumHandler.php b/src/Migration/MessageQueue/Handler/ResetChecksumHandler.php new file mode 100644 index 000000000..483af8053 --- /dev/null +++ b/src/Migration/MessageQueue/Handler/ResetChecksumHandler.php @@ -0,0 +1,181 @@ + + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace SwagMigrationAssistant\Migration\MessageQueue\Handler; + +use Doctrine\DBAL\Connection; +use Doctrine\DBAL\ParameterType; +use Shopware\Core\Framework\DataAbstractionLayer\EntityRepository; +use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria; +use Shopware\Core\Framework\Log\Package; +use Shopware\Core\Framework\Uuid\Uuid; +use SwagMigrationAssistant\Migration\DataSelection\DefaultEntities; +use SwagMigrationAssistant\Migration\MessageQueue\Message\MigrationProcessMessage; +use SwagMigrationAssistant\Migration\MessageQueue\Message\ResetChecksumMessage; +use SwagMigrationAssistant\Migration\Run\MigrationProgress; +use SwagMigrationAssistant\Migration\Run\MigrationStep; +use SwagMigrationAssistant\Migration\Run\ProgressDataSetCollection; +use SwagMigrationAssistant\Migration\Run\RunTransitionServiceInterface; +use SwagMigrationAssistant\Migration\Run\SwagMigrationRunCollection; +use Symfony\Component\Messenger\Attribute\AsMessageHandler; +use Symfony\Component\Messenger\MessageBusInterface; + +/** + * @internal + */ +#[AsMessageHandler] +#[Package('fundamentals@after-sales')] +final readonly class ResetChecksumHandler +{ + public const BATCH_SIZE = 250; + + /** + * @param EntityRepository $migrationRunRepo + */ + public function __construct( + private Connection $connection, + private MessageBusInterface $messageBus, + private EntityRepository $migrationRunRepo, + private RunTransitionServiceInterface $runTransitionService, + ) { + } + + public function __invoke(ResetChecksumMessage $message): void + { + $connectionId = $message->getConnectionId(); + $totalMappings = $message->getTotalMappings(); + + if ($totalMappings === null) { + $totalMappings = $this->getTotalMappingsCount($connectionId); + } + + $affectedRows = $this->resetChecksums($connectionId); + $newProcessedCount = $message->getProcessedMappings() + $affectedRows; + + $isCompleted = $affectedRows < self::BATCH_SIZE; + + if ($isCompleted) { + $this->handleCompletion($message); + + if ($message->isPartOfAbort()) { + return; + } + } + + if ($message->getRunId() !== null && $totalMappings > 0) { + $this->updateProgress($message, $newProcessedCount, $totalMappings); + } + + if (!$isCompleted) { + $this->messageBus->dispatch(new ResetChecksumMessage( + $message->getConnectionId(), + $message->getContext(), + $message->getRunId(), + $message->getEntity(), + $totalMappings, + $newProcessedCount, + $message->isPartOfAbort() + )); + } + } + + private function handleCompletion(ResetChecksumMessage $message): void + { + $this->clearResettingChecksumsFlag(); + $runId = $message->getRunId(); + + if (!$message->isPartOfAbort() || $runId === null) { + return; + } + + $this->runTransitionService->forceTransitionToRunStep( + $runId, + MigrationStep::CLEANUP + ); + + $this->updateProgress($message, 0, 0, true); + + $this->messageBus->dispatch(new MigrationProcessMessage( + $message->getContext(), + $runId, + )); + } + + private function resetChecksums(string $connectionId): int + { + return (int) $this->connection->executeStatement( + 'UPDATE swag_migration_mapping + SET checksum = NULL + WHERE checksum IS NOT NULL + AND connection_id = :connectionId + LIMIT :limit', + [ + 'connectionId' => Uuid::fromHexToBytes($connectionId), + 'limit' => self::BATCH_SIZE, + ], + [ + 'connectionId' => ParameterType::BINARY, + 'limit' => ParameterType::INTEGER, + ] + ); + } + + private function getTotalMappingsCount(string $connectionId): int + { + return (int) $this->connection->createQueryBuilder() + ->select('COUNT(m.id)') + ->from('swag_migration_mapping', 'm') + ->where('m.checksum IS NOT NULL') + ->andWhere('m.connection_id = :connectionId') + ->setParameter('connectionId', Uuid::fromHexToBytes($connectionId)) + ->executeQuery() + ->fetchOne(); + } + + private function updateProgress(ResetChecksumMessage $message, int $processed, int $total, bool $isAborted = false): void + { + $runId = $message->getRunId(); + + if ($runId === null) { + return; + } + + $run = $this->migrationRunRepo->search( + new Criteria([$runId]), + $message->getContext(), + )->getEntities()->first(); + + if ($run === null) { + return; + } + + $progress = $run->getProgress(); + $newProgress = new MigrationProgress( + $processed, + $total, + $progress?->getDataSets() ?? new ProgressDataSetCollection(), + $message->getEntity() ?? DefaultEntities::RULE, + $processed + ); + + if ($isAborted) { + $newProgress->setIsAborted(true); + } + + $this->migrationRunRepo->update([[ + 'id' => $runId, + 'progress' => $newProgress->jsonSerialize(), + ]], $message->getContext()); + } + + private function clearResettingChecksumsFlag(): void + { + $this->connection->executeStatement( + 'UPDATE swag_migration_general_setting SET `is_resetting_checksums` = 0;' + ); + } +} diff --git a/src/Migration/MessageQueue/Handler/CleanupMigrationHandler.php b/src/Migration/MessageQueue/Handler/TruncateMigrationHandler.php similarity index 53% rename from src/Migration/MessageQueue/Handler/CleanupMigrationHandler.php rename to src/Migration/MessageQueue/Handler/TruncateMigrationHandler.php index 536118b91..79cd8978b 100644 --- a/src/Migration/MessageQueue/Handler/CleanupMigrationHandler.php +++ b/src/Migration/MessageQueue/Handler/TruncateMigrationHandler.php @@ -9,7 +9,7 @@ use Doctrine\DBAL\Connection; use Shopware\Core\Framework\Log\Package; -use SwagMigrationAssistant\Migration\MessageQueue\Message\CleanupMigrationMessage; +use SwagMigrationAssistant\Migration\MessageQueue\Message\TruncateMigrationMessage; use Symfony\Component\Messenger\Attribute\AsMessageHandler; use Symfony\Component\Messenger\MessageBusInterface; @@ -18,15 +18,17 @@ /** * @internal */ -final class CleanupMigrationHandler +final class TruncateMigrationHandler { + private const BATCH_SIZE = 250; + public function __construct( private readonly Connection $connection, private readonly MessageBusInterface $bus, ) { } - public function __invoke(CleanupMigrationMessage $message): void + public function __invoke(TruncateMigrationMessage $message): void { $currentStep = 0; $tablesToReset = [ @@ -38,16 +40,40 @@ public function __invoke(CleanupMigrationMessage $message): void 'swag_migration_connection', ]; - $step = \array_search($message->getTableName(), $tablesToReset, true); + $step = \array_search( + $message->getTableName(), + $tablesToReset, + true + ); + if ($step !== false) { $currentStep = $step; } + $affectedRows = (int) $this->connection->executeStatement( + 'DELETE FROM ' . $tablesToReset[$currentStep] . ' LIMIT ' . self::BATCH_SIZE + ); + + if ($affectedRows >= self::BATCH_SIZE) { + $this->bus->dispatch(new TruncateMigrationMessage( + $tablesToReset[$currentStep] + )); + + return; + } + $nextStep = $currentStep + 1; + if (isset($tablesToReset[$nextStep])) { - $nextMessage = new CleanupMigrationMessage($tablesToReset[$nextStep]); - $this->bus->dispatch($nextMessage); + $this->bus->dispatch(new TruncateMigrationMessage( + $tablesToReset[$nextStep] + )); + + return; } - $this->connection->executeStatement('DELETE FROM ' . $tablesToReset[$currentStep] . ';'); + + $this->connection->executeStatement( + 'UPDATE swag_migration_general_setting SET `is_reset` = 0;' + ); } } diff --git a/src/Migration/MessageQueue/Message/ResetChecksumMessage.php b/src/Migration/MessageQueue/Message/ResetChecksumMessage.php new file mode 100644 index 000000000..94af5c3be --- /dev/null +++ b/src/Migration/MessageQueue/Message/ResetChecksumMessage.php @@ -0,0 +1,62 @@ + + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace SwagMigrationAssistant\Migration\MessageQueue\Message; + +use Shopware\Core\Framework\Context; +use Shopware\Core\Framework\Log\Package; +use Shopware\Core\Framework\MessageQueue\AsyncMessageInterface; + +#[Package('fundamentals@after-sales')] +readonly class ResetChecksumMessage implements AsyncMessageInterface +{ + public function __construct( + private string $connectionId, + private Context $context, + private ?string $runId = null, + private ?string $entity = null, + private ?int $totalMappings = null, + private int $processedMappings = 0, + private bool $isPartOfAbort = false, + ) { + } + + public function getConnectionId(): string + { + return $this->connectionId; + } + + public function getContext(): Context + { + return $this->context; + } + + public function getRunId(): ?string + { + return $this->runId; + } + + public function getEntity(): ?string + { + return $this->entity; + } + + public function getTotalMappings(): ?int + { + return $this->totalMappings; + } + + public function getProcessedMappings(): int + { + return $this->processedMappings; + } + + public function isPartOfAbort(): bool + { + return $this->isPartOfAbort; + } +} diff --git a/src/Migration/MessageQueue/Message/CleanupMigrationMessage.php b/src/Migration/MessageQueue/Message/TruncateMigrationMessage.php similarity index 90% rename from src/Migration/MessageQueue/Message/CleanupMigrationMessage.php rename to src/Migration/MessageQueue/Message/TruncateMigrationMessage.php index db9025c46..864521af8 100644 --- a/src/Migration/MessageQueue/Message/CleanupMigrationMessage.php +++ b/src/Migration/MessageQueue/Message/TruncateMigrationMessage.php @@ -11,7 +11,7 @@ use Shopware\Core\Framework\MessageQueue\AsyncMessageInterface; #[Package('fundamentals@after-sales')] -class CleanupMigrationMessage implements AsyncMessageInterface +class TruncateMigrationMessage implements AsyncMessageInterface { public function __construct(private readonly ?string $tableName = null) { diff --git a/src/Migration/MigrationContext.php b/src/Migration/MigrationContext.php index f82105710..547f63dff 100644 --- a/src/Migration/MigrationContext.php +++ b/src/Migration/MigrationContext.php @@ -9,6 +9,7 @@ use Shopware\Core\Framework\Log\Package; use Shopware\Core\Framework\Struct\Struct; +use SwagMigrationAssistant\Exception\MigrationException; use SwagMigrationAssistant\Migration\Connection\SwagMigrationConnectionEntity; use SwagMigrationAssistant\Migration\DataSelection\DataSet\DataSet; use SwagMigrationAssistant\Migration\Gateway\GatewayInterface; @@ -19,46 +20,55 @@ class MigrationContext extends Struct implements MigrationContextInterface { final public const SOURCE_CONTEXT = 'MIGRATION_CONNECTION_CHECK_FOR_RUNNING_MIGRATION'; - private ProfileInterface $profile; - - private ?SwagMigrationConnectionEntity $connection; - - private string $runUuid; + public function __construct( + private SwagMigrationConnectionEntity $connection, + private ?ProfileInterface $profile = null, + private ?GatewayInterface $gateway = null, + private ?DataSet $dataSet = null, + private readonly string $runUuid = '', + private int $offset = 0, + private int $limit = 0, + ) { + } - private ?DataSet $dataSet; + public function getProfile(): ProfileInterface + { + if ($this->profile === null) { + throw MigrationException::migrationContextPropertyMissing('profile'); + } - private int $offset; + return $this->profile; + } - private int $limit; + public function setProfile(ProfileInterface $profile): void + { + $this->profile = $profile; + } - private GatewayInterface $gateway; + public function getGateway(): GatewayInterface + { + if ($this->gateway === null) { + throw MigrationException::migrationContextPropertyMissing('gateway'); + } - public function __construct( - ProfileInterface $profile, - ?SwagMigrationConnectionEntity $connection = null, - string $runUuid = '', - ?DataSet $dataSet = null, - int $offset = 0, - int $limit = 0, - ) { - $this->profile = $profile; - $this->connection = $connection; - $this->runUuid = $runUuid; - $this->dataSet = $dataSet; - $this->offset = $offset; - $this->limit = $limit; + return $this->gateway; } - public function getProfile(): ProfileInterface + public function setGateway(GatewayInterface $gateway): void { - return $this->profile; + $this->gateway = $gateway; } - public function getConnection(): ?SwagMigrationConnectionEntity + public function getConnection(): SwagMigrationConnectionEntity { return $this->connection; } + public function setConnection(SwagMigrationConnectionEntity $connection): void + { + $this->connection = $connection; + } + public function getRunUuid(): string { return $this->runUuid; @@ -79,18 +89,18 @@ public function getOffset(): int return $this->offset; } - public function getLimit(): int + public function setOffset(int $offset): void { - return $this->limit; + $this->offset = $offset; } - public function getGateway(): GatewayInterface + public function getLimit(): int { - return $this->gateway; + return $this->limit; } - public function setGateway(GatewayInterface $gateway): void + public function setLimit(int $limit): void { - $this->gateway = $gateway; + $this->limit = $limit; } } diff --git a/src/Migration/MigrationContextFactory.php b/src/Migration/MigrationContextFactory.php index db3fe037f..b892ff071 100644 --- a/src/Migration/MigrationContextFactory.php +++ b/src/Migration/MigrationContextFactory.php @@ -22,18 +22,18 @@ use SwagMigrationAssistant\Migration\Setting\GeneralSettingEntity; #[Package('fundamentals@after-sales')] -class MigrationContextFactory implements MigrationContextFactoryInterface +readonly class MigrationContextFactory implements MigrationContextFactoryInterface { /** * @param EntityRepository $generalSettingRepository * @param EntityRepository $migrationConnectionRepository */ public function __construct( - private readonly ProfileRegistryInterface $profileRegistry, - private readonly GatewayRegistryInterface $gatewayRegistry, - private readonly DataSetRegistryInterface $dataSetRegistry, - private readonly EntityRepository $generalSettingRepository, - private readonly EntityRepository $migrationConnectionRepository, + private ProfileRegistryInterface $profileRegistry, + private GatewayRegistryInterface $gatewayRegistry, + private DataSetRegistryInterface $dataSetRegistry, + private EntityRepository $generalSettingRepository, + private EntityRepository $migrationConnectionRepository, ) { } @@ -44,19 +44,23 @@ public function create( string $entity = '', ): ?MigrationContextInterface { $connection = $run->getConnection(); + if ($connection === null) { return null; } $profile = $this->profileRegistry->getProfile($connection->getProfileName()); + $migrationContext = new MigrationContext( - $profile, $connection, - $run->getId(), + $profile, null, + null, + $run->getId(), $offset, $limit ); + $gateway = $this->gatewayRegistry->getGateway($migrationContext); $migrationContext->setGateway($gateway); @@ -68,25 +72,18 @@ public function create( return $migrationContext; } - public function createByProfileName(string $profileName): MigrationContextInterface - { - $profile = $this->profileRegistry->getProfile($profileName); - - return new MigrationContext( - $profile - ); - } - public function createByConnection( SwagMigrationConnectionEntity $connection, ): MigrationContextInterface { $profile = $this->profileRegistry->getProfile( $connection->getProfileName() ); + $migrationContext = new MigrationContext( + $connection, $profile, - $connection ); + $gateway = $this->gatewayRegistry->getGateway($migrationContext); $migrationContext->setGateway($gateway); @@ -96,17 +93,27 @@ public function createByConnection( public function createBySelectedConnection(Context $context): MigrationContextInterface { $settings = $this->generalSettingRepository->search(new Criteria(), $context)->first(); + if (!$settings instanceof GeneralSettingEntity) { throw MigrationException::entityNotExists(GeneralSettingEntity::class, 'Default'); } if ($settings->getSelectedConnectionId() === null) { - throw MigrationException::noConnectionIsSelected(); + throw MigrationException::noConnectionFound(); } - $connection = $this->migrationConnectionRepository->search(new Criteria([$settings->getSelectedConnectionId()]), $context)->first(); + $connection = $this->migrationConnectionRepository->search( + new Criteria( + [$settings->getSelectedConnectionId()] + ), + $context + )->first(); + if (!$connection instanceof SwagMigrationConnectionEntity) { - throw MigrationException::entityNotExists(SwagMigrationConnectionEntity::class, $settings->getSelectedConnectionId()); + throw MigrationException::entityNotExists( + SwagMigrationConnectionEntity::class, + $settings->getSelectedConnectionId() + ); } return $this->createByConnection($connection); diff --git a/src/Migration/MigrationContextFactoryInterface.php b/src/Migration/MigrationContextFactoryInterface.php index 234ad85ea..88ed520e9 100644 --- a/src/Migration/MigrationContextFactoryInterface.php +++ b/src/Migration/MigrationContextFactoryInterface.php @@ -17,8 +17,6 @@ interface MigrationContextFactoryInterface { public function create(SwagMigrationRunEntity $run, int $offset = 0, int $limit = 0, string $entity = ''): ?MigrationContextInterface; - public function createByProfileName(string $profileName): MigrationContextInterface; - public function createByConnection(SwagMigrationConnectionEntity $connection): MigrationContextInterface; public function createBySelectedConnection(Context $context): MigrationContextInterface; diff --git a/src/Migration/MigrationContextInterface.php b/src/Migration/MigrationContextInterface.php index 60da42ce4..8acac406d 100644 --- a/src/Migration/MigrationContextInterface.php +++ b/src/Migration/MigrationContextInterface.php @@ -18,7 +18,15 @@ interface MigrationContextInterface { public function getProfile(): ProfileInterface; - public function getConnection(): ?SwagMigrationConnectionEntity; + public function setProfile(ProfileInterface $profile): void; + + public function getGateway(): GatewayInterface; + + public function setGateway(GatewayInterface $gateway): void; + + public function getConnection(): SwagMigrationConnectionEntity; + + public function setConnection(SwagMigrationConnectionEntity $connection): void; public function getRunUuid(): string; @@ -26,9 +34,9 @@ public function getDataSet(): ?DataSet; public function getOffset(): int; - public function getLimit(): int; + public function setOffset(int $offset): void; - public function getGateway(): GatewayInterface; + public function getLimit(): int; - public function setGateway(GatewayInterface $gateway): void; + public function setLimit(int $limit): void; } diff --git a/src/Migration/Premapping/AbstractPremappingReader.php b/src/Migration/Premapping/AbstractPremappingReader.php index a659af993..fdf173cd8 100644 --- a/src/Migration/Premapping/AbstractPremappingReader.php +++ b/src/Migration/Premapping/AbstractPremappingReader.php @@ -20,12 +20,8 @@ abstract class AbstractPremappingReader implements PremappingReaderInterface protected function fillConnectionPremappingDictionary(MigrationContextInterface $migrationContext): void { - $connection = $migrationContext->getConnection(); - if ($connection === null) { - return; - } + $connectionMapping = $migrationContext->getConnection()->getPremapping(); - $connectionMapping = $connection->getPremapping(); if ($connectionMapping === null) { return; } diff --git a/src/Migration/Run/MigrationProgressFieldSerializer.php b/src/Migration/Run/MigrationProgressFieldSerializer.php index 3736d4416..d0b5b9cf7 100644 --- a/src/Migration/Run/MigrationProgressFieldSerializer.php +++ b/src/Migration/Run/MigrationProgressFieldSerializer.php @@ -44,12 +44,15 @@ public function encode( $dataSet = $dataSet->jsonSerialize(); } } + + unset($dataSet); } if (isset($value['dataSets']) && \is_array($value['dataSets'])) { foreach ($value['dataSets'] as &$dataSet) { unset($dataSet['extensions']); } + unset($dataSet); } $data = new KeyValuePair($data->getKey(), $value, $data->isRaw()); diff --git a/src/Migration/Run/MigrationStep.php b/src/Migration/Run/MigrationStep.php index 3e8b900d1..e2070efd6 100644 --- a/src/Migration/Run/MigrationStep.php +++ b/src/Migration/Run/MigrationStep.php @@ -16,6 +16,8 @@ enum MigrationStep: string case FETCHING = 'fetching'; + case ERROR_RESOLUTION = 'error-resolution'; + case WRITING = 'writing'; case MEDIA_PROCESSING = 'media-processing'; @@ -39,4 +41,12 @@ public function isRunning(): bool self::ABORTED, ], true); } + + public function needsProcessor(): bool + { + return !\in_array($this, [ + self::ERROR_RESOLUTION, + self::WAITING_FOR_APPROVE, + ], true); + } } diff --git a/src/Migration/Run/RunService.php b/src/Migration/Run/RunService.php index c007637b1..54ca805a4 100644 --- a/src/Migration/Run/RunService.php +++ b/src/Migration/Run/RunService.php @@ -10,20 +10,17 @@ use Doctrine\DBAL\Connection; use Doctrine\DBAL\ParameterType; use Shopware\Core\Framework\Context; -use Shopware\Core\Framework\DataAbstractionLayer\Dbal\QueryBuilder; -use Shopware\Core\Framework\DataAbstractionLayer\EntityDefinition; use Shopware\Core\Framework\DataAbstractionLayer\EntityRepository; use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria; use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsFilter; use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\MultiFilter; use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\NotFilter; -use Shopware\Core\Framework\DataAbstractionLayer\Search\Sorting\FieldSorting; use Shopware\Core\Framework\Log\Package; use Shopware\Core\Framework\Store\Services\TrackingEventClient; -use Shopware\Core\Framework\Uuid\Uuid; use Shopware\Core\System\SalesChannel\SalesChannelCollection; use Shopware\Core\System\SalesChannel\SalesChannelDefinition; use Shopware\Storefront\Theme\ThemeCollection; +use Shopware\Storefront\Theme\ThemeDefinition; use Shopware\Storefront\Theme\ThemeService; use SwagMigrationAssistant\Exception\MigrationException; use SwagMigrationAssistant\Migration\Connection\SwagMigrationConnectionCollection; @@ -31,11 +28,13 @@ use SwagMigrationAssistant\Migration\DataSelection\DataSelectionCollection; use SwagMigrationAssistant\Migration\DataSelection\DataSelectionRegistryInterface; use SwagMigrationAssistant\Migration\EnvironmentInformation; +use SwagMigrationAssistant\Migration\Logging\Log\Builder\MigrationLogBuilder; use SwagMigrationAssistant\Migration\Logging\Log\ThemeCompilingErrorRunLog; use SwagMigrationAssistant\Migration\Logging\LoggingServiceInterface; use SwagMigrationAssistant\Migration\Mapping\MappingServiceInterface; -use SwagMigrationAssistant\Migration\MessageQueue\Message\CleanupMigrationMessage; use SwagMigrationAssistant\Migration\MessageQueue\Message\MigrationProcessMessage; +use SwagMigrationAssistant\Migration\MessageQueue\Message\ResetChecksumMessage; +use SwagMigrationAssistant\Migration\MessageQueue\Message\TruncateMigrationMessage; use SwagMigrationAssistant\Migration\MigrationContext; use SwagMigrationAssistant\Migration\MigrationContextFactoryInterface; use SwagMigrationAssistant\Migration\MigrationContextInterface; @@ -68,7 +67,6 @@ public function __construct( private readonly EntityRepository $generalSettingRepo, private readonly ThemeService $themeService, private readonly MappingServiceInterface $mappingService, - private readonly EntityDefinition $migrationDataDefinition, private readonly Connection $dbalConnection, private readonly LoggingServiceInterface $loggingService, private readonly TrackingEventClient $trackingEventClient, @@ -82,13 +80,17 @@ public function __construct( public function startMigrationRun(array $dataSelectionIds, Context $context): void { if ($this->isMigrationRunning($context)) { - throw MigrationException::migrationIsAlreadyRunning(); + throw MigrationException::migrationProcessing(); + } + + if ($this->isResettingChecksums()) { + throw MigrationException::migrationProcessing('checksum reset'); } $connection = $this->getCurrentConnection($context); if ($connection === null) { - throw MigrationException::noConnectionIsSelected(); + throw MigrationException::noConnectionFound(); } if (!$this->isPremmappingValid($dataSelectionIds, $connection, $context)) { @@ -96,9 +98,6 @@ public function startMigrationRun(array $dataSelectionIds, Context $context): vo } $connectionId = $connection->getId(); - // ToDo: MIG-965 - Check how we could put this into the MQ - $this->cleanupUnwrittenRunDataOfLastInactiveRun($context); - $runUuid = $this->createPlainMigrationRun($connectionId, $context); if ($runUuid === null) { @@ -135,12 +134,12 @@ public function getRunStatus(Context $context): MigrationState } /** - * @param array|null $credentialFields + * @param array|null $credentialFields */ public function updateConnectionCredentials(Context $context, string $connectionUuid, ?array $credentialFields): void { if ($this->isMigrationRunning($context)) { - throw MigrationException::migrationIsAlreadyRunning(); + throw MigrationException::migrationProcessing(); } $context->scope(MigrationContext::SOURCE_CONTEXT, function (Context $context) use ($connectionUuid, $credentialFields): void { @@ -158,49 +157,50 @@ public function abortMigration(Context $context): void $run = $this->getActiveRun($context); if ($run === null) { - throw MigrationException::noRunningMigration(); + throw MigrationException::runNotFound(); } $runId = $run->getId(); $runningSteps = [ MigrationStep::FETCHING->value, + MigrationStep::ERROR_RESOLUTION->value, MigrationStep::WRITING->value, MigrationStep::MEDIA_PROCESSING->value, ]; if (!\in_array($run->getStepValue(), $runningSteps, true)) { - throw MigrationException::noRunningMigration(); + throw MigrationException::runNotFound(); } $this->runTransitionService->transitionToRunStep($runId, MigrationStep::ABORTING); + $this->bus->dispatch(new MigrationProcessMessage($context, $runId)); $this->fireTrackingInformation(self::TRACKING_EVENT_MIGRATION_ABORTED, $runId, $context); } - public function cleanupMappingChecksums(string $connectionUuid, Context $context, bool $resetAll = true): void + public function startCleanupMappingChecksums(string $connectionId, Context $context): void { - $sql = <<connectionRepo->search( + new Criteria([$connectionId]), + $context, + )->getEntities()->first(); + + if ($connection === null) { + throw MigrationException::noConnectionFound(); } - $this->dbalConnection->executeStatement( - $sql, - [$connectionUuid], - [ParameterType::STRING] + $affectedRows = $this->dbalConnection->executeStatement( + 'UPDATE swag_migration_general_setting SET `is_resetting_checksums` = 1 WHERE `is_resetting_checksums` = 0;' ); + + if ($affectedRows === 0) { + throw MigrationException::migrationProcessing('checksum reset'); + } + + $this->bus->dispatch(new ResetChecksumMessage( + $connectionId, + $context, + )); } public function approveFinishingMigration(Context $context): void @@ -208,11 +208,11 @@ public function approveFinishingMigration(Context $context): void $run = $this->getActiveRun($context); if ($run === null) { - throw MigrationException::noRunningMigration(); + throw MigrationException::runNotFound(); } if ($run->getStep() !== MigrationStep::WAITING_FOR_APPROVE) { - throw MigrationException::noRunToFinish(); + throw MigrationException::runNotFound(); } $this->runTransitionService->transitionToRunStep($run->getId(), MigrationStep::FINISHED); @@ -220,14 +220,21 @@ public function approveFinishingMigration(Context $context): void $this->fireTrackingInformation(self::TRACKING_EVENT_MIGRATION_FINISHED, $run->getId(), $context); } - public function cleanupMigrationData(Context $context): void + public function startTruncateMigrationData(Context $context): void { if ($this->isMigrationRunning($context)) { - throw MigrationException::migrationIsAlreadyRunning(); + throw MigrationException::migrationProcessing(); + } + + $affectedRows = $this->dbalConnection->executeStatement( + 'UPDATE swag_migration_general_setting SET selected_connection_id = NULL, `is_reset` = 1 WHERE `is_reset` = 0;' + ); + + if ($affectedRows === 0) { + throw MigrationException::migrationProcessing('data truncation'); } - $this->dbalConnection->executeStatement('UPDATE swag_migration_general_setting SET selected_connection_id = NULL, `is_reset` = 1;'); - $this->bus->dispatch(new CleanupMigrationMessage()); + $this->bus->dispatch(new TruncateMigrationMessage()); } public function assignThemeToSalesChannel(string $runUuid, Context $context): void @@ -244,27 +251,54 @@ public function assignThemeToSalesChannel(string $runUuid, Context $context): vo } $connectionId = $connection->getId(); - $salesChannels = $this->getSalesChannels($connectionId, $context); - $defaultTheme = $this->getDefaultTheme($context); + $salesChannelIds = $this->getSalesChannels($connectionId, $context); + $defaultThemeId = $this->getDefaultTheme($context); - if ($defaultTheme === null) { + if ($defaultThemeId === null) { return; } - foreach ($salesChannels as $salesChannel) { + foreach ($salesChannelIds as $salesChannelId) { try { - $this->themeService->assignTheme($defaultTheme, $salesChannel, $context); + $this->themeService->assignTheme($defaultThemeId, $salesChannelId, $context); } catch (\Throwable $exception) { - $this->loggingService->addLogEntry(new ThemeCompilingErrorRunLog( - $runUuid, - $defaultTheme - )); + $this->loggingService->addLogEntry( + (new MigrationLogBuilder( + $runUuid, + $connection->getProfileName(), + $connection->getGatewayName(), + )) + ->withExceptionMessage($exception->getMessage()) + ->withExceptionTrace($exception->getTrace()) + ->withEntityName(ThemeDefinition::ENTITY_NAME) + ->withEntityId($defaultThemeId) + ->build(ThemeCompilingErrorRunLog::class) + ); } } $this->loggingService->saveLogging($context); } + public function resumeAfterFixes(Context $context): void + { + $run = $this->getActiveRun($context); + + if ($run === null) { + throw MigrationException::runNotFound(); + } + + $runId = $run->getId(); + + if ($run->getStepValue() !== MigrationStep::ERROR_RESOLUTION->value) { + throw MigrationException::migrationNotInStep($runId, MigrationStep::ERROR_RESOLUTION->value); + } + + $this->runTransitionService->transitionToRunStep($runId, MigrationStep::WRITING); + + $this->bus->dispatch(new MigrationProcessMessage($context, $runId)); + } + /** * @param array $dataSelectionIds */ @@ -301,17 +335,11 @@ private function isMigrationRunning(Context $context): bool return $this->getActiveRun($context) !== null; } - private function getLastInactiveRun(Context $context): ?SwagMigrationRunEntity + private function isResettingChecksums(): bool { - $criteria = new Criteria(); - $criteria->addFilter(new MultiFilter(MultiFilter::CONNECTION_OR, [ - new EqualsFilter('step', MigrationStep::ABORTED->value), - new EqualsFilter('step', MigrationStep::FINISHED->value), - ])); - $criteria->addSorting(new FieldSorting('createdAt', 'DESC')); - $criteria->setLimit(1); - - return $this->migrationRunRepo->search($criteria, $context)->getEntities()->first(); + return (bool) $this->dbalConnection->fetchOne( + 'SELECT is_resetting_checksums FROM swag_migration_general_setting LIMIT 1' + ); } private function fireTrackingInformation(string $eventName, string $runUuid, Context $context): void @@ -543,21 +571,6 @@ private function getDefaultTheme(Context $context): ?string return \reset($ids); } - private function cleanupUnwrittenRunDataOfLastInactiveRun(Context $context): void - { - $lastInactiveRun = $this->getLastInactiveRun($context); - - if ($lastInactiveRun === null) { - return; - } - - $queryBuilder = new QueryBuilder($this->dbalConnection); - $queryBuilder->delete($this->migrationDataDefinition->getEntityName()) - ->andWhere('run_id = :runId') - ->setParameter('runId', Uuid::fromHexToBytes($lastInactiveRun->getId())) - ->executeStatement(); - } - private function updateUnprocessedMediaFiles(string $connectionId, string $runUuid): void { $sql = << FETCHING -> WRITING -> MEDIA_PROCESSING -> CLEANUP -> INDEXING -> WAITING_FOR_APPROVE -> IDLE + * IDLE -> FETCHING -> ERROR_RESOLUTION -> WRITING -> MEDIA_PROCESSING -> CLEANUP -> INDEXING -> WAITING_FOR_APPROVE -> IDLE * * If the migration run is aborted, the steps are as follows: - * IDLE -> [FETCHING || WRITING || MEDIA_PROCESSING] -> ABORTING -> CLEANUP -> INDEXING -> IDLE + * IDLE -> [FETCHING || ERROR_RESOLUTION || WRITING || MEDIA_PROCESSING] -> ABORTING -> CLEANUP -> INDEXING -> IDLE */ public function getRunStatus(Context $context): MigrationState; /** * Abort the running migration. - * If no migration run is running or the current migration is not in the FETCHING or WRITING or MEDIA_PROCESSING step, it throws a NoRunningMigrationException. + * If no migration run is running or the current migration is not in the FETCHING or WRITING or MEDIA_PROCESSING step, it throws a MigrationException. * - * @throws NoRunningMigrationException + * @throws MigrationException */ public function abortMigration(Context $context): void; - public function cleanupMappingChecksums(string $connectionUuid, Context $context): void; + public function startCleanupMappingChecksums(string $connectionUuid, Context $context): void; + + public function startTruncateMigrationData(Context $context): void; /** * @param array $dataSelectionIds @@ -50,5 +52,5 @@ public function approveFinishingMigration(Context $context): void; public function assignThemeToSalesChannel(string $runUuid, Context $context): void; - public function cleanupMigrationData(Context $context): void; + public function resumeAfterFixes(Context $context): void; } diff --git a/src/Migration/Service/MediaFileProcessorService.php b/src/Migration/Service/MediaFileProcessorService.php index 09ccc695b..d4c8c2c56 100644 --- a/src/Migration/Service/MediaFileProcessorService.php +++ b/src/Migration/Service/MediaFileProcessorService.php @@ -11,9 +11,10 @@ use Shopware\Core\Framework\Context; use Shopware\Core\Framework\Log\Package; use Shopware\Core\Framework\Uuid\Uuid; -use SwagMigrationAssistant\Exception\DataSetNotFoundException; +use SwagMigrationAssistant\Exception\MigrationException; use SwagMigrationAssistant\Migration\DataSelection\DataSet\DataSet; use SwagMigrationAssistant\Migration\DataSelection\DataSet\DataSetRegistry; +use SwagMigrationAssistant\Migration\Logging\Log\Builder\MigrationLogBuilder; use SwagMigrationAssistant\Migration\Logging\Log\DataSetNotFoundLog; use SwagMigrationAssistant\Migration\Logging\LoggingService; use SwagMigrationAssistant\Migration\MessageQueue\Message\ProcessMediaMessage; @@ -40,14 +41,19 @@ public function processMediaFiles(MigrationContextInterface $migrationContext, C $currentDataSet = null; $currentCount = 0; $messageMediaUuids = []; + foreach ($mediaFiles as $mediaFile) { if ($currentDataSet === null) { try { $currentDataSet = $this->dataSetRegistry->getDataSet($migrationContext, $mediaFile['entity']); - } catch (DataSetNotFoundException $e) { - $this->logDataSetNotFoundException($migrationContext, $mediaFile); + } catch (MigrationException $exception) { + if ($exception->getErrorCode() === MigrationException::DATASET_NOT_FOUND) { + $this->logDataSetNotFoundException($migrationContext, $exception); + + continue; + } - continue; + throw $exception; } } @@ -58,10 +64,14 @@ public function processMediaFiles(MigrationContextInterface $migrationContext, C $messageMediaUuids = []; $currentCount = 0; $currentDataSet = $this->dataSetRegistry->getDataSet($migrationContext, $mediaFile['entity']); - } catch (DataSetNotFoundException $e) { - $this->logDataSetNotFoundException($migrationContext, $mediaFile); + } catch (MigrationException $exception) { + if ($exception->getErrorCode() === MigrationException::DATASET_NOT_FOUND) { + $this->logDataSetNotFoundException($migrationContext, $exception); - continue; + continue; + } + + throw $exception; } } @@ -128,26 +138,15 @@ private function addMessageToBus(string $runUuid, Context $context, DataSet $dat $this->messageBus->dispatch($message); } - /** - * @param array $mediaFile - */ private function logDataSetNotFoundException( MigrationContextInterface $migrationContext, - array $mediaFile, + \Throwable $exception, ): void { - $connection = $migrationContext->getConnection(); - - if ($connection === null) { - return; - } - $this->loggingService->addLogEntry( - new DataSetNotFoundLog( - $migrationContext->getRunUuid(), - $mediaFile['entity'], - $mediaFile['id'], - $connection->getProfileName() - ) + MigrationLogBuilder::fromMigrationContext($migrationContext) + ->withExceptionMessage($exception->getMessage()) + ->withExceptionTrace($exception->getTrace()) + ->build(DataSetNotFoundLog::class) ); } } diff --git a/src/Migration/Service/MigrationDataConverter.php b/src/Migration/Service/MigrationDataConverter.php index ab6d8cdb4..8f3a39687 100644 --- a/src/Migration/Service/MigrationDataConverter.php +++ b/src/Migration/Service/MigrationDataConverter.php @@ -12,15 +12,20 @@ use Shopware\Core\Framework\DataAbstractionLayer\Write\EntityWriterInterface; use Shopware\Core\Framework\DataAbstractionLayer\Write\WriteContext; use Shopware\Core\Framework\Log\Package; +use Shopware\Core\Framework\Util\Hasher; use SwagMigrationAssistant\Migration\Converter\ConverterInterface; use SwagMigrationAssistant\Migration\Converter\ConverterRegistryInterface; +use SwagMigrationAssistant\Migration\Converter\ConvertStruct; use SwagMigrationAssistant\Migration\DataSelection\DataSet\DataSet; +use SwagMigrationAssistant\Migration\Logging\Log\Builder\MigrationLogBuilder; use SwagMigrationAssistant\Migration\Logging\Log\ExceptionRunLog; +use SwagMigrationAssistant\Migration\Logging\Log\NotConvertedLog; use SwagMigrationAssistant\Migration\Logging\LoggingServiceInterface; use SwagMigrationAssistant\Migration\Mapping\MappingDeltaResult; use SwagMigrationAssistant\Migration\Mapping\MappingServiceInterface; use SwagMigrationAssistant\Migration\Media\MediaFileServiceInterface; use SwagMigrationAssistant\Migration\MigrationContextInterface; +use SwagMigrationAssistant\Migration\Validation\MigrationValidationService; #[Package('fundamentals@after-sales')] class MigrationDataConverter implements MigrationDataConverterInterface @@ -32,6 +37,7 @@ public function __construct( private readonly LoggingServiceInterface $loggingService, private readonly EntityDefinition $dataDefinition, private readonly MappingServiceInterface $mappingService, + private readonly MigrationValidationService $validationService, ) { } @@ -67,11 +73,14 @@ public function convert(array $data, MigrationContextInterface $migrationContext $this->mediaFileService->writeMediaFile($context); } } catch (\Throwable $exception) { - $this->loggingService->addLogEntry(new ExceptionRunLog( - $migrationContext->getRunUuid(), - $dataSet::getEntity(), - $exception - )); + $this->loggingService->addLogEntry( + MigrationLogBuilder::fromMigrationContext($migrationContext) + ->withExceptionMessage($exception->getMessage()) + ->withExceptionTrace($exception->getTrace()) + ->withEntityName($dataSet::getEntity()) + ->build(ExceptionRunLog::class) + ); + $this->loggingService->saveLogging($context); } } @@ -89,8 +98,27 @@ private function convertData( foreach ($data as $item) { try { $convertStruct = $converter->convert($item, $context, $migrationContext); + if (!$convertStruct instanceof ConvertStruct) { + $this->loggingService->addLogEntry( + MigrationLogBuilder::fromMigrationContext($migrationContext) + ->withSourceData($item) + ->withEntityName($dataSet::getEntity()) + ->build(NotConvertedLog::class) + ); + + continue; + } + $convertFailureFlag = empty($convertStruct->getConverted()); + $this->validationService->validate( + $migrationContext, + $context, + $convertStruct->getConverted(), + $dataSet::getEntity(), + $item + ); + $createData[] = [ 'entity' => $dataSet::getEntity(), 'runId' => $runUuid, @@ -101,12 +129,14 @@ private function convertData( 'convertFailure' => $convertFailureFlag, ]; } catch (\Throwable $exception) { - $this->loggingService->addLogEntry(new ExceptionRunLog( - $runUuid, - $dataSet::getEntity(), - $exception, - $item['id'] ?? null - )); + $this->loggingService->addLogEntry( + MigrationLogBuilder::fromMigrationContext($migrationContext) + ->withExceptionMessage($exception->getMessage()) + ->withExceptionTrace($exception->getTrace()) + ->withEntityName($dataSet::getEntity()) + ->withSourceData($item) + ->build(ExceptionRunLog::class) + ); $createData[] = [ 'entity' => $dataSet::getEntity(), @@ -137,17 +167,16 @@ private function filterDeltas(array $data, ConverterInterface $converter, Migrat foreach ($data as $dataSet) { $mappedData[$converter->getSourceIdentifier($dataSet)] = $dataSet; - $checksums[$converter->getSourceIdentifier($dataSet)] = \md5(\serialize($dataSet)); + $checksums[$converter->getSourceIdentifier($dataSet)] = Hasher::hash(\serialize($dataSet)); } - $connection = $migrationContext->getConnection(); $dataSet = $migrationContext->getDataSet(); - if ($connection === null || $dataSet === null) { + if ($dataSet === null) { return new MappingDeltaResult(); } - $connectionId = $connection->getId(); + $connectionId = $migrationContext->getConnection()->getId(); $entity = $dataSet::getEntity(); $result = $this->mappingService->getMappings($connectionId, $entity, \array_keys($checksums), $context); diff --git a/src/Migration/Service/MigrationDataFetcher.php b/src/Migration/Service/MigrationDataFetcher.php index 1bfcf9ea6..be4565177 100644 --- a/src/Migration/Service/MigrationDataFetcher.php +++ b/src/Migration/Service/MigrationDataFetcher.php @@ -11,6 +11,7 @@ use Shopware\Core\Framework\Log\Package; use SwagMigrationAssistant\Migration\EnvironmentInformation; use SwagMigrationAssistant\Migration\Gateway\GatewayRegistryInterface; +use SwagMigrationAssistant\Migration\Logging\Log\Builder\MigrationLogBuilder; use SwagMigrationAssistant\Migration\Logging\Log\ExceptionRunLog; use SwagMigrationAssistant\Migration\Logging\LoggingServiceInterface; use SwagMigrationAssistant\Migration\MigrationContextInterface; @@ -34,11 +35,13 @@ public function fetchData(MigrationContextInterface $migrationContext, Context $ try { return $this->gatewayRegistry->getGateway($migrationContext)->read($migrationContext); } catch (\Throwable $exception) { - $this->loggingService->addLogEntry(new ExceptionRunLog( - $migrationContext->getRunUuid(), - $dataSet::getEntity(), - $exception - )); + $this->loggingService->addLogEntry( + MigrationLogBuilder::fromMigrationContext($migrationContext) + ->withExceptionMessage($exception->getMessage()) + ->withExceptionTrace($exception->getTrace()) + ->withEntityName($dataSet::getEntity()) + ->build(ExceptionRunLog::class) + ); $this->loggingService->saveLogging($context); } diff --git a/src/Migration/Service/MigrationDataWriter.php b/src/Migration/Service/MigrationDataWriter.php index f64147710..c62982dd0 100644 --- a/src/Migration/Service/MigrationDataWriter.php +++ b/src/Migration/Service/MigrationDataWriter.php @@ -12,14 +12,18 @@ use Shopware\Core\Framework\DataAbstractionLayer\EntityDefinition; use Shopware\Core\Framework\DataAbstractionLayer\EntityRepository; use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria; +use Shopware\Core\Framework\DataAbstractionLayer\Search\EntitySearchResult; use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsFilter; use Shopware\Core\Framework\DataAbstractionLayer\Search\Sorting\FieldSorting; use Shopware\Core\Framework\DataAbstractionLayer\Write\EntityWriterInterface; use Shopware\Core\Framework\DataAbstractionLayer\Write\WriteContext; use Shopware\Core\Framework\DataAbstractionLayer\Write\WriteException; use Shopware\Core\Framework\Log\Package; -use SwagMigrationAssistant\Exception\WriterNotFoundException; +use SwagMigrationAssistant\Exception\MigrationException; use SwagMigrationAssistant\Migration\Data\SwagMigrationDataCollection; +use SwagMigrationAssistant\Migration\Data\SwagMigrationDataEntity; +use SwagMigrationAssistant\Migration\ErrorResolution\MigrationErrorResolutionService; +use SwagMigrationAssistant\Migration\Logging\Log\Builder\MigrationLogBuilder; use SwagMigrationAssistant\Migration\Logging\Log\ExceptionRunLog; use SwagMigrationAssistant\Migration\Logging\Log\WriteExceptionRunLog; use SwagMigrationAssistant\Migration\Logging\LoggingServiceInterface; @@ -45,6 +49,7 @@ public function __construct( private readonly LoggingServiceInterface $loggingService, private readonly EntityDefinition $dataDefinition, private readonly EntityRepository $mappingRepo, + private readonly MigrationErrorResolutionService $errorResolutionService, ) { // write / upsert entities only with this single context, // otherwise the migration behaves differently when started in the administration @@ -100,15 +105,26 @@ public function writeData(MigrationContextInterface $migrationContext, Context $ return 0; } + $convertedValues = array_values($converted); + $this->errorResolutionService->applyFixes( + $convertedValues, + $migrationContext->getConnection()->getId(), + $migrationContext->getRunUuid(), + $context + ); + try { $currentWriter = $this->writerRegistry->getWriter($dataSet::getEntity()); - $currentWriter->writeData(\array_values($converted), $this->writeContext); - } catch (WriterNotFoundException $writerNotFoundException) { - $this->loggingService->addLogEntry(new ExceptionRunLog( - $migrationContext->getRunUuid(), - $dataSet::getEntity(), - $writerNotFoundException - )); + $currentWriter->writeData($convertedValues, $this->writeContext); + } catch (MigrationException $writerNotFoundException) { + $this->loggingService->addLogEntry( + MigrationLogBuilder::fromMigrationContext($migrationContext) + ->withExceptionMessage($writerNotFoundException->getMessage()) + ->withExceptionTrace($writerNotFoundException->getTrace()) + ->withConvertedData([$converted]) + ->withEntityName($dataSet::getEntity()) + ->build(ExceptionRunLog::class) + ); $this->loggingService->saveLogging($context); foreach ($updateWrittenData as &$data) { @@ -125,11 +141,12 @@ public function writeData(MigrationContextInterface $migrationContext, Context $ $dataSet::getEntity(), $updateWrittenData, $migrationContext, - $context + $context, + $migrationData ); - } catch (\Throwable $exception) { + } catch (\Throwable) { // Worst case: something unknown goes wrong (most likely some foreign key constraint that fails) - $this->writePerEntity($converted, $dataSet::getEntity(), $updateWrittenData, $migrationContext, $context); + $this->writePerEntity($converted, $dataSet::getEntity(), $updateWrittenData, $migrationContext); } finally { // Update written-Flag of the entity in the data table $this->entityWriter->update( @@ -154,6 +171,7 @@ public function writeData(MigrationContextInterface $migrationContext, Context $ /** * @param array $converted * @param array $updateWrittenData + * @param EntitySearchResult $migrationData */ private function handleWriteException( WriteException $exception, @@ -162,6 +180,7 @@ private function handleWriteException( array &$updateWrittenData, MigrationContextInterface $migrationContext, Context $context, + EntitySearchResult $migrationData, ): void { $writeErrors = $this->extractWriteErrorsWithIndex($exception); $currentWriter = $this->writerRegistry->getWriter($entityName); @@ -178,12 +197,21 @@ private function handleWriteException( $updateWrittenData[$dataId]['written'] = false; $updateWrittenData[$dataId]['writeFailure'] = true; - $this->loggingService->addLogEntry(new WriteExceptionRunLog( - $migrationContext->getRunUuid(), - $entityName, - $writeErrors[$index], - $dataId - )); + + $currentData = $migrationData->firstWhere(function (SwagMigrationDataEntity $item) use ($dataId) { + return $item->getId() === $dataId; + }); + + $this->loggingService->addLogEntry( + MigrationLogBuilder::fromMigrationContext($migrationContext) + ->withExceptionMessage($exception->getMessage()) + ->withExceptionTrace($exception->getTrace()) + ->withEntityName($entityName) + ->withConvertedData($entity) + ->withEntityId($entity['id'] ?? null) + ->withSourceData($currentData?->getRaw() ?? []) + ->build(WriteExceptionRunLog::class) + ); ++$index; } @@ -194,8 +222,8 @@ private function handleWriteException( try { $currentWriter->writeData($newData, $this->writeContext); - } catch (\Throwable $exception) { - $this->writePerEntity($converted, $entityName, $updateWrittenData, $migrationContext, $context); + } catch (\Throwable) { + $this->writePerEntity($converted, $entityName, $updateWrittenData, $migrationContext); } } @@ -227,19 +255,21 @@ private function writePerEntity( string $entityName, array &$updateWrittenData, MigrationContextInterface $migrationContext, - Context $context, ): void { foreach ($converted as $dataId => $entity) { try { $currentWriter = $this->writerRegistry->getWriter($entityName); $currentWriter->writeData([$entity], $this->writeContext); } catch (\Throwable $exception) { - $this->loggingService->addLogEntry(new ExceptionRunLog( - $migrationContext->getRunUuid(), - $entityName, - $exception, - $dataId - )); + $this->loggingService->addLogEntry( + MigrationLogBuilder::fromMigrationContext($migrationContext) + ->withExceptionMessage($exception->getMessage()) + ->withExceptionTrace($exception->getTrace()) + ->withEntityName($entityName) + ->withConvertedData([$entity]) + ->withEntityId($entity['id'] ?? null) + ->build(ExceptionRunLog::class) + ); $updateWrittenData[$dataId]['written'] = false; $updateWrittenData[$dataId]['writeFailure'] = true; diff --git a/src/Migration/Service/PremappingService.php b/src/Migration/Service/PremappingService.php index 71d5a6f61..fb34741e2 100644 --- a/src/Migration/Service/PremappingService.php +++ b/src/Migration/Service/PremappingService.php @@ -68,10 +68,6 @@ public function writePremapping(Context $context, MigrationContextInterface $mig $connection = $migrationContext->getConnection(); - if ($connection === null) { - return; - } - foreach ($premapping as $item) { $entity = $item['entity']; @@ -118,13 +114,8 @@ public function writePremapping(Context $context, MigrationContextInterface $mig */ private function updateConnectionPremapping(Context $context, MigrationContextInterface $migrationContext, array $premapping): void { - $premapping = $this->updateConnectionPremappingStruct($migrationContext, $premapping); - $connection = $migrationContext->getConnection(); - - if ($connection === null) { - return; - } + $premapping = $this->updateConnectionPremappingStruct($migrationContext, $premapping); $this->connectionRepo->update( [ @@ -144,13 +135,7 @@ private function updateConnectionPremapping(Context $context, MigrationContextIn */ private function updateConnectionPremappingStruct(MigrationContextInterface $migrationContext, array $premapping): array { - $connection = $migrationContext->getConnection(); - - if ($connection === null) { - return []; - } - - $connectionPremapping = $connection->getPremapping(); + $connectionPremapping = $migrationContext->getConnection()->getPremapping(); if ($connectionPremapping === null) { $connectionPremapping = []; diff --git a/src/Migration/Setting/GeneralSettingDefinition.php b/src/Migration/Setting/GeneralSettingDefinition.php index e96767518..d075d466d 100644 --- a/src/Migration/Setting/GeneralSettingDefinition.php +++ b/src/Migration/Setting/GeneralSettingDefinition.php @@ -46,6 +46,7 @@ protected function defineFields(): FieldCollection (new IdField('id', 'id'))->addFlags(new PrimaryKey(), new Required()), new FkField('selected_connection_id', 'selectedConnectionId', SwagMigrationConnectionDefinition::class), new BoolField('is_reset', 'isReset'), + new BoolField('is_resetting_checksums', 'isResettingChecksums'), new CreatedAtField(), new UpdatedAtField(), new ManyToOneAssociationField('selectedConnection', 'selected_connection_id', SwagMigrationConnectionDefinition::class, 'id', true), diff --git a/src/Migration/Setting/GeneralSettingEntity.php b/src/Migration/Setting/GeneralSettingEntity.php index 8497e7baa..43dc70884 100644 --- a/src/Migration/Setting/GeneralSettingEntity.php +++ b/src/Migration/Setting/GeneralSettingEntity.php @@ -23,6 +23,8 @@ class GeneralSettingEntity extends Entity protected bool $isReset; + protected bool $isResettingChecksums = false; + public function getSelectedConnectionId(): ?string { return $this->selectedConnectionId; @@ -52,4 +54,14 @@ public function setIsReset(bool $isReset): void { $this->isReset = $isReset; } + + public function isResettingChecksums(): bool + { + return $this->isResettingChecksums; + } + + public function setIsResettingChecksums(bool $isResettingChecksums): void + { + $this->isResettingChecksums = $isResettingChecksums; + } } diff --git a/src/Migration/Subscriber/MessageQueueSubscriber.php b/src/Migration/Subscriber/MessageQueueSubscriber.php index 1449a6350..0756cca52 100644 --- a/src/Migration/Subscriber/MessageQueueSubscriber.php +++ b/src/Migration/Subscriber/MessageQueueSubscriber.php @@ -11,8 +11,9 @@ use Shopware\Core\Framework\DataAbstractionLayer\EntityRepository; use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria; use Shopware\Core\Framework\Log\Package; +use SwagMigrationAssistant\Migration\Logging\Log\Builder\MigrationLogBuilder; use SwagMigrationAssistant\Migration\Logging\Log\MessageQueueExceptionLog; -use SwagMigrationAssistant\Migration\Logging\Log\RunAbortedAutomatically; +use SwagMigrationAssistant\Migration\Logging\Log\RunAbortedAutomaticallyLog; use SwagMigrationAssistant\Migration\Logging\LoggingServiceInterface; use SwagMigrationAssistant\Migration\MessageQueue\Message\MigrationProcessMessage; use SwagMigrationAssistant\Migration\Run\MigrationProgress; @@ -82,11 +83,22 @@ public function onWorkerMessageFailed(WorkerMessageFailedEvent $event): void return; } + $connection = $run->getConnection(); + /* * Raise exception counter and log the exception */ $progress->raiseExceptionCount(); - $this->loggingService->addLogEntry(new MessageQueueExceptionLog($run->getId(), $event->getThrowable(), $progress->getExceptionCount())); + $this->loggingService->addLogEntry( + (new MigrationLogBuilder( + $run->getId(), + $connection?->getProfileName() ?? 'unknown', + $connection?->getGatewayName() ?? 'unknown' + )) + ->withExceptionMessage($event->getThrowable()->getMessage()) + ->withExceptionTrace($event->getThrowable()->getTrace()) + ->build(MessageQueueExceptionLog::class) + ); /* * Check if run is already in aborting state and failed again there, then set run status to aborted and log the error. @@ -96,7 +108,16 @@ public function onWorkerMessageFailed(WorkerMessageFailedEvent $event): void $progress->setIsAborted(true); $this->updateRun($run->getId(), $progress, $message->getContext()); - $this->loggingService->addLogEntry(new RunAbortedAutomatically($run->getId(), $event->getThrowable())); + $this->loggingService->addLogEntry( + (new MigrationLogBuilder( + $run->getId(), + $connection?->getProfileName() ?? 'unknown', + $connection?->getGatewayName() ?? 'unknown' + )) + ->withExceptionMessage($event->getThrowable()->getMessage()) + ->withExceptionTrace($event->getThrowable()->getTrace()) + ->build(RunAbortedAutomaticallyLog::class) + ); $this->loggingService->saveLogging($message->getContext()); return; diff --git a/src/Migration/Validation/Event/MigrationPostValidationEvent.php b/src/Migration/Validation/Event/MigrationPostValidationEvent.php new file mode 100644 index 000000000..9c4a63a31 --- /dev/null +++ b/src/Migration/Validation/Event/MigrationPostValidationEvent.php @@ -0,0 +1,40 @@ + + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace SwagMigrationAssistant\Migration\Validation\Event; + +use Shopware\Core\Framework\Context; +use Shopware\Core\Framework\Event\ShopwareEvent; +use Shopware\Core\Framework\Log\Package; +use SwagMigrationAssistant\Migration\Validation\MigrationValidationContext; +use Symfony\Contracts\EventDispatcher\Event; + +/** + * @final + * + * @codeCoverageIgnore + */ +#[Package('fundamentals@after-sales')] +class MigrationPostValidationEvent extends Event implements ShopwareEvent +{ + /** + * @internal + */ + public function __construct(private readonly MigrationValidationContext $validationContext) + { + } + + public function getValidationContext(): MigrationValidationContext + { + return $this->validationContext; + } + + public function getContext(): Context + { + return $this->validationContext->getContext(); + } +} diff --git a/src/Migration/Validation/Event/MigrationPreValidationEvent.php b/src/Migration/Validation/Event/MigrationPreValidationEvent.php new file mode 100644 index 000000000..7af6c21aa --- /dev/null +++ b/src/Migration/Validation/Event/MigrationPreValidationEvent.php @@ -0,0 +1,40 @@ + + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace SwagMigrationAssistant\Migration\Validation\Event; + +use Shopware\Core\Framework\Context; +use Shopware\Core\Framework\Event\ShopwareEvent; +use Shopware\Core\Framework\Log\Package; +use SwagMigrationAssistant\Migration\Validation\MigrationValidationContext; +use Symfony\Contracts\EventDispatcher\Event; + +/** + * @final + * + * @codeCoverageIgnore + */ +#[Package('fundamentals@after-sales')] +class MigrationPreValidationEvent extends Event implements ShopwareEvent +{ + /** + * @internal + */ + public function __construct(private readonly MigrationValidationContext $validationContext) + { + } + + public function getValidationContext(): MigrationValidationContext + { + return $this->validationContext; + } + + public function getContext(): Context + { + return $this->validationContext->getContext(); + } +} diff --git a/src/Migration/Validation/Log/MigrationValidationExceptionLog.php b/src/Migration/Validation/Log/MigrationValidationExceptionLog.php new file mode 100644 index 000000000..74507d172 --- /dev/null +++ b/src/Migration/Validation/Log/MigrationValidationExceptionLog.php @@ -0,0 +1,30 @@ + + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace SwagMigrationAssistant\Migration\Validation\Log; + +use Shopware\Core\Framework\Log\Package; +use SwagMigrationAssistant\Migration\Logging\Log\Builder\AbstractMigrationLogEntry; + +#[Package('fundamentals@after-sales')] +readonly class MigrationValidationExceptionLog extends AbstractMigrationLogEntry +{ + public function isUserFixable(): bool + { + return false; + } + + public function getLevel(): string + { + return self::LOG_LEVEL_ERROR; + } + + public function getCode(): string + { + return 'SWAG_MIGRATION_VALIDATION_EXCEPTION'; + } +} diff --git a/src/Migration/Validation/Log/MigrationValidationInvalidFieldValueLog.php b/src/Migration/Validation/Log/MigrationValidationInvalidFieldValueLog.php new file mode 100644 index 000000000..5b5340165 --- /dev/null +++ b/src/Migration/Validation/Log/MigrationValidationInvalidFieldValueLog.php @@ -0,0 +1,30 @@ + + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace SwagMigrationAssistant\Migration\Validation\Log; + +use Shopware\Core\Framework\Log\Package; +use SwagMigrationAssistant\Migration\Logging\Log\Builder\AbstractMigrationLogEntry; + +#[Package('fundamentals@after-sales')] +readonly class MigrationValidationInvalidFieldValueLog extends AbstractMigrationLogEntry +{ + public function isUserFixable(): bool + { + return true; + } + + public function getLevel(): string + { + return self::LOG_LEVEL_ERROR; + } + + public function getCode(): string + { + return 'SWAG_MIGRATION_VALIDATION_INVALID_FIELD_VALUE'; + } +} diff --git a/src/Migration/Validation/Log/MigrationValidationInvalidForeignKeyLog.php b/src/Migration/Validation/Log/MigrationValidationInvalidForeignKeyLog.php new file mode 100644 index 000000000..bdd2a0ae3 --- /dev/null +++ b/src/Migration/Validation/Log/MigrationValidationInvalidForeignKeyLog.php @@ -0,0 +1,30 @@ + + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace SwagMigrationAssistant\Migration\Validation\Log; + +use Shopware\Core\Framework\Log\Package; +use SwagMigrationAssistant\Migration\Logging\Log\Builder\AbstractMigrationLogEntry; + +#[Package('fundamentals@after-sales')] +readonly class MigrationValidationInvalidForeignKeyLog extends AbstractMigrationLogEntry +{ + public function isUserFixable(): bool + { + return true; + } + + public function getLevel(): string + { + return self::LOG_LEVEL_WARNING; + } + + public function getCode(): string + { + return 'SWAG_MIGRATION_VALIDATION_INVALID_FOREIGN_KEY'; + } +} diff --git a/src/Migration/Validation/Log/MigrationValidationMissingRequiredFieldLog.php b/src/Migration/Validation/Log/MigrationValidationMissingRequiredFieldLog.php new file mode 100644 index 000000000..fb39b8810 --- /dev/null +++ b/src/Migration/Validation/Log/MigrationValidationMissingRequiredFieldLog.php @@ -0,0 +1,30 @@ + + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace SwagMigrationAssistant\Migration\Validation\Log; + +use Shopware\Core\Framework\Log\Package; +use SwagMigrationAssistant\Migration\Logging\Log\Builder\AbstractMigrationLogEntry; + +#[Package('fundamentals@after-sales')] +readonly class MigrationValidationMissingRequiredFieldLog extends AbstractMigrationLogEntry +{ + public function isUserFixable(): bool + { + return false; + } + + public function getLevel(): string + { + return self::LOG_LEVEL_ERROR; + } + + public function getCode(): string + { + return 'SWAG_MIGRATION_VALIDATION_MISSING_REQUIRED_FIELD'; + } +} diff --git a/src/Migration/Validation/Log/MigrationValidationUnexpectedFieldLog.php b/src/Migration/Validation/Log/MigrationValidationUnexpectedFieldLog.php new file mode 100644 index 000000000..d363bf846 --- /dev/null +++ b/src/Migration/Validation/Log/MigrationValidationUnexpectedFieldLog.php @@ -0,0 +1,30 @@ + + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace SwagMigrationAssistant\Migration\Validation\Log; + +use Shopware\Core\Framework\Log\Package; +use SwagMigrationAssistant\Migration\Logging\Log\Builder\AbstractMigrationLogEntry; + +#[Package('fundamentals@after-sales')] +readonly class MigrationValidationUnexpectedFieldLog extends AbstractMigrationLogEntry +{ + public function isUserFixable(): bool + { + return true; + } + + public function getLevel(): string + { + return self::LOG_LEVEL_WARNING; + } + + public function getCode(): string + { + return 'SWAG_MIGRATION_VALIDATION_UNEXPECTED_FIELD'; + } +} diff --git a/src/Migration/Validation/MigrationValidationContext.php b/src/Migration/Validation/MigrationValidationContext.php new file mode 100644 index 000000000..a606665ea --- /dev/null +++ b/src/Migration/Validation/MigrationValidationContext.php @@ -0,0 +1,78 @@ + + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace SwagMigrationAssistant\Migration\Validation; + +use Shopware\Core\Framework\Context; +use Shopware\Core\Framework\DataAbstractionLayer\EntityDefinition; +use Shopware\Core\Framework\Log\Package; +use SwagMigrationAssistant\Migration\MigrationContextInterface; + +/** + * @final + * + * @codeCoverageIgnore + */ +#[Package('fundamentals@after-sales')] +readonly class MigrationValidationContext +{ + protected MigrationValidationResult $validationResult; + + /** + * @internal + * + * @param array $convertedData + * @param array $sourceData + */ + public function __construct( + protected Context $shopwareContext, + protected MigrationContextInterface $migrationContext, + protected EntityDefinition $entityDefinition, + protected array $convertedData, + protected array $sourceData, + ) { + $this->validationResult = new MigrationValidationResult( + $this->entityDefinition->getEntityName(), + ); + } + + public function getContext(): Context + { + return $this->shopwareContext; + } + + public function getMigrationContext(): MigrationContextInterface + { + return $this->migrationContext; + } + + /** + * @return array + */ + public function getConvertedData(): array + { + return $this->convertedData; + } + + /** + * @return array + */ + public function getSourceData(): array + { + return $this->sourceData; + } + + public function getEntityDefinition(): EntityDefinition + { + return $this->entityDefinition; + } + + public function getValidationResult(): MigrationValidationResult + { + return $this->validationResult; + } +} diff --git a/src/Migration/Validation/MigrationValidationResult.php b/src/Migration/Validation/MigrationValidationResult.php new file mode 100644 index 000000000..48fc13147 --- /dev/null +++ b/src/Migration/Validation/MigrationValidationResult.php @@ -0,0 +1,50 @@ + + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace SwagMigrationAssistant\Migration\Validation; + +use Shopware\Core\Framework\Log\Package; +use SwagMigrationAssistant\Migration\Logging\Log\Builder\MigrationLogEntry; + +/** + * @final + */ +#[Package('fundamentals@after-sales')] +class MigrationValidationResult +{ + /** + * @param MigrationLogEntry[] $logs + */ + public function __construct( + private readonly string $entityName, + private array $logs = [], + ) { + } + + public function addLog(MigrationLogEntry $log): void + { + $this->logs[] = $log; + } + + /** + * @return MigrationLogEntry[] + */ + public function getLogs(): array + { + return $this->logs; + } + + public function hasLogs(): bool + { + return \count($this->logs) !== 0; + } + + public function getEntityName(): string + { + return $this->entityName; + } +} diff --git a/src/Migration/Validation/MigrationValidationService.php b/src/Migration/Validation/MigrationValidationService.php new file mode 100644 index 000000000..e1d939c2a --- /dev/null +++ b/src/Migration/Validation/MigrationValidationService.php @@ -0,0 +1,255 @@ + + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace SwagMigrationAssistant\Migration\Validation; + +use Shopware\Core\Framework\Context; +use Shopware\Core\Framework\DataAbstractionLayer\DefinitionInstanceRegistry; +use Shopware\Core\Framework\DataAbstractionLayer\Field\Field; +use Shopware\Core\Framework\DataAbstractionLayer\Field\FkField; +use Shopware\Core\Framework\DataAbstractionLayer\Field\Flag\Required; +use Shopware\Core\Framework\DataAbstractionLayer\Write\Command\WriteCommandQueue; +use Shopware\Core\Framework\DataAbstractionLayer\Write\DataStack\KeyValuePair; +use Shopware\Core\Framework\DataAbstractionLayer\Write\EntityExistence; +use Shopware\Core\Framework\DataAbstractionLayer\Write\WriteContext; +use Shopware\Core\Framework\DataAbstractionLayer\Write\WriteParameterBag; +use Shopware\Core\Framework\Log\Package; +use Shopware\Core\Framework\Uuid\Uuid; +use SwagMigrationAssistant\Exception\MigrationException; +use SwagMigrationAssistant\Migration\Logging\Log\Builder\MigrationLogBuilder; +use SwagMigrationAssistant\Migration\Logging\LoggingServiceInterface; +use SwagMigrationAssistant\Migration\Mapping\MappingServiceInterface; +use SwagMigrationAssistant\Migration\MigrationContextInterface; +use SwagMigrationAssistant\Migration\Validation\Event\MigrationPostValidationEvent; +use SwagMigrationAssistant\Migration\Validation\Event\MigrationPreValidationEvent; +use SwagMigrationAssistant\Migration\Validation\Log\MigrationValidationExceptionLog; +use SwagMigrationAssistant\Migration\Validation\Log\MigrationValidationInvalidFieldValueLog; +use SwagMigrationAssistant\Migration\Validation\Log\MigrationValidationInvalidForeignKeyLog; +use SwagMigrationAssistant\Migration\Validation\Log\MigrationValidationMissingRequiredFieldLog; +use SwagMigrationAssistant\Migration\Validation\Log\MigrationValidationUnexpectedFieldLog; +use Symfony\Contracts\EventDispatcher\EventDispatcherInterface; + +/** + * @internal + */ +#[Package('fundamentals@after-sales')] +readonly class MigrationValidationService +{ + public function __construct( + private DefinitionInstanceRegistry $definitionRegistry, + private EventDispatcherInterface $eventDispatcher, + private LoggingServiceInterface $loggingService, + private MappingServiceInterface $mappingService, + ) { + } + + /** + * @param array|null $convertedEntity + * @param array $sourceData + */ + public function validate( + MigrationContextInterface $migrationContext, + Context $shopwareContext, + ?array $convertedEntity, + string $entityName, + array $sourceData, + ): ?MigrationValidationResult { + if (empty($convertedEntity)) { + return null; + } + + $entityDefinition = $this->definitionRegistry->getByEntityName($entityName); + + $validationContext = new MigrationValidationContext( + $shopwareContext, + $migrationContext, + $entityDefinition, + $convertedEntity, + $sourceData, + ); + + $this->eventDispatcher->dispatch( + new MigrationPreValidationEvent($validationContext), + ); + + try { + $this->validateEntityStructure($validationContext); + $this->validateFields($validationContext); + $this->validateAssociations($validationContext); + } catch (\Throwable $exception) { + $validationContext->getValidationResult()->addLog( + MigrationLogBuilder::fromMigrationContext($validationContext->getMigrationContext()) + ->withEntityName($validationContext->getEntityDefinition()->getEntityName()) + ->withSourceData($validationContext->getSourceData()) + ->withConvertedData($validationContext->getConvertedData()) + ->withExceptionMessage($exception->getMessage()) + ->withExceptionTrace($exception->getTrace()) + ->withEntityId($convertedEntity['id'] ?? null) + ->build(MigrationValidationExceptionLog::class) + ); + } + + $this->eventDispatcher->dispatch( + new MigrationPostValidationEvent($validationContext), + ); + + foreach ($validationContext->getValidationResult()->getLogs() as $log) { + $this->loggingService->addLogEntry($log); + } + + $this->loggingService->saveLogging($validationContext->getContext()); + + return $validationContext->getValidationResult(); + } + + private function validateEntityStructure(MigrationValidationContext $validationContext): void + { + $fields = $validationContext->getEntityDefinition()->getFields(); + + $requiredFields = array_values(array_map( + static fn (Field $field) => $field->getPropertyName(), + $fields->filterByFlag(Required::class)->getElements() + )); + + $convertedFieldNames = array_keys($validationContext->getConvertedData()); + $missingRequiredFields = array_diff($requiredFields, $convertedFieldNames); + + foreach ($missingRequiredFields as $missingField) { + $validationContext->getValidationResult()->addLog( + MigrationLogBuilder::fromMigrationContext($validationContext->getMigrationContext()) + ->withEntityName($validationContext->getEntityDefinition()->getEntityName()) + ->withFieldName($missingField) + ->withConvertedData($validationContext->getConvertedData()) + ->withEntityId($validationContext->getConvertedData()['id'] ?? null) + ->build(MigrationValidationMissingRequiredFieldLog::class) + ); + } + + $unexpectedFields = array_diff($convertedFieldNames, array_keys($fields->getElements())); + + foreach ($unexpectedFields as $unexpectedField) { + $validationContext->getValidationResult()->addLog( + MigrationLogBuilder::fromMigrationContext($validationContext->getMigrationContext()) + ->withEntityName($validationContext->getEntityDefinition()->getEntityName()) + ->withFieldName($unexpectedField) + ->withConvertedData($validationContext->getConvertedData()) + ->withEntityId($validationContext->getConvertedData()['id'] ?? null) + ->build(MigrationValidationUnexpectedFieldLog::class) + ); + } + } + + private function validateFields(MigrationValidationContext $validationContext): void + { + $fields = $validationContext->getEntityDefinition()->getFields(); + + if (!isset($validationContext->getConvertedData()['id'])) { + throw MigrationException::unexpectedNullValue('id'); + } + + if (!Uuid::isValid($validationContext->getConvertedData()['id'])) { + throw MigrationException::invalidId($validationContext->getConvertedData()['id'], $validationContext->getEntityDefinition()->getEntityName()); + } + + $entityExistence = EntityExistence::createForEntity( + $validationContext->getEntityDefinition()->getEntityName(), + ['id' => $validationContext->getConvertedData()['id']], + ); + + $parameters = new WriteParameterBag( + $validationContext->getEntityDefinition(), + WriteContext::createFromContext($validationContext->getContext()), + '', + new WriteCommandQueue(), + ); + + foreach ($validationContext->getConvertedData() as $fieldName => $value) { + if (!$fields->has($fieldName)) { + continue; + } + + $field = clone $fields->get($fieldName); + $field->setFlags(new Required()); + + $keyValue = new KeyValuePair( + $field->getPropertyName(), + $value, + true + ); + + try { + $serializer = $field->getSerializer(); + \iterator_to_array($serializer->encode($field, $entityExistence, $keyValue, $parameters), false); + } catch (\Throwable $e) { + $validationContext->getValidationResult()->addLog( + MigrationLogBuilder::fromMigrationContext($validationContext->getMigrationContext()) + ->withEntityName($validationContext->getEntityDefinition()->getEntityName()) + ->withFieldName($fieldName) + ->withConvertedData([$fieldName => $value]) + ->withSourceData($validationContext->getSourceData()) + ->withExceptionMessage($e->getMessage()) + ->withExceptionTrace($e->getTrace()) + ->withEntityId($validationContext->getConvertedData()['id'] ?? null) + ->build(MigrationValidationInvalidFieldValueLog::class) + ); + } + } + } + + private function validateAssociations(MigrationValidationContext $validationContext): void + { + $fields = $validationContext->getEntityDefinition()->getFields(); + + $fkFields = array_values(array_map( + static fn (Field $field) => $field->getPropertyName(), + $fields->filterInstance(FkField::class)->getElements() + )); + + foreach ($fkFields as $fkFieldName) { + if (!isset($validationContext->getConvertedData()[$fkFieldName])) { + continue; + } + + $fkValue = $validationContext->getConvertedData()[$fkFieldName]; + + if ($fkValue === '') { + continue; + } + + $fkField = $fields->get($fkFieldName); + + if (!$fkField instanceof FkField) { + throw MigrationException::unexpectedNullValue($fkFieldName); + } + + $referenceEntity = $fkField->getReferenceEntity(); + + if (!$referenceEntity) { + throw MigrationException::unexpectedNullValue($fkFieldName); + } + + $hasMapping = $this->mappingService->hasValidMappingByEntityId( + $validationContext->getMigrationContext()->getConnection()->getId(), + $referenceEntity, + $fkValue, + $validationContext->getContext() + ); + + if (!$hasMapping) { + $validationContext->getValidationResult()->addLog( + MigrationLogBuilder::fromMigrationContext($validationContext->getMigrationContext()) + ->withEntityName($validationContext->getEntityDefinition()->getEntityName()) + ->withFieldName($fkFieldName) + ->withConvertedData([$fkFieldName => $fkValue]) + ->withSourceData($validationContext->getSourceData()) + ->withEntityId($validationContext->getConvertedData()['id'] ?? null) + ->build(MigrationValidationInvalidForeignKeyLog::class) + ); + } + } + } +} diff --git a/src/Migration/Writer/WriterRegistryInterface.php b/src/Migration/Writer/WriterRegistryInterface.php index 124ec2bfc..9ad95de7a 100644 --- a/src/Migration/Writer/WriterRegistryInterface.php +++ b/src/Migration/Writer/WriterRegistryInterface.php @@ -8,7 +8,7 @@ namespace SwagMigrationAssistant\Migration\Writer; use Shopware\Core\Framework\Log\Package; -use SwagMigrationAssistant\Exception\WriterNotFoundException; +use SwagMigrationAssistant\Exception\MigrationException; #[Package('fundamentals@after-sales')] interface WriterRegistryInterface @@ -16,7 +16,7 @@ interface WriterRegistryInterface /** * Returns the writer which supports the given entity * - * @throws WriterNotFoundException + * @throws MigrationException */ public function getWriter(string $entityName): WriterInterface; } diff --git a/src/Profile/Shopware/Converter/AttributeConverter.php b/src/Profile/Shopware/Converter/AttributeConverter.php index 629301665..c236ce1ea 100644 --- a/src/Profile/Shopware/Converter/AttributeConverter.php +++ b/src/Profile/Shopware/Converter/AttributeConverter.php @@ -39,12 +39,8 @@ public function convert(array $data, Context $context, MigrationContextInterface $converted = []; $connection = $migrationContext->getConnection(); - $this->connectionId = ''; - $this->connectionName = ''; - if ($connection !== null) { - $this->connectionId = $connection->getId(); - $this->connectionName = $connection->getName(); - } + $this->connectionId = $connection->getId(); + $this->connectionName = $connection->getName(); $mapping = $this->mappingService->getOrCreateMapping( $this->connectionId, @@ -52,7 +48,7 @@ public function convert(array $data, Context $context, MigrationContextInterface $this->getCustomFieldEntityName() . 'CustomFieldSet', $context ); - $converted['id'] = $mapping['entityUuid']; + $converted['id'] = $mapping['entityId']; $this->mappingIds[] = $mapping['id']; $connectionName = ConnectionNameSanitizer::sanitize($this->connectionName); @@ -74,7 +70,7 @@ public function convert(array $data, Context $context, MigrationContextInterface $converted['relations'] = [ [ - 'id' => $mapping['entityUuid'], + 'id' => $mapping['entityId'], 'entityName' => $this->getCustomFieldEntityName(), ], ]; @@ -95,7 +91,7 @@ public function convert(array $data, Context $context, MigrationContextInterface $converted['customFields'] = [ [ - 'id' => $this->mainMapping['entityUuid'], + 'id' => $this->mainMapping['entityId'], 'name' => $converted['name'] . '_' . $data['name'], 'type' => $this->getCustomFieldType($data), 'config' => $this->getCustomFieldConfiguration($data), diff --git a/src/Profile/Shopware/Converter/CategoryConverter.php b/src/Profile/Shopware/Converter/CategoryConverter.php index 95edfc0c3..dfacd188a 100644 --- a/src/Profile/Shopware/Converter/CategoryConverter.php +++ b/src/Profile/Shopware/Converter/CategoryConverter.php @@ -14,7 +14,6 @@ use SwagMigrationAssistant\Exception\MigrationException; use SwagMigrationAssistant\Migration\Converter\ConvertStruct; use SwagMigrationAssistant\Migration\DataSelection\DefaultEntities; -use SwagMigrationAssistant\Migration\Logging\Log\EmptyNecessaryFieldRunLog; use SwagMigrationAssistant\Migration\Logging\LoggingServiceInterface; use SwagMigrationAssistant\Migration\Mapping\Lookup\DefaultCmsPageLookup; use SwagMigrationAssistant\Migration\Mapping\Lookup\LanguageLookup; @@ -36,7 +35,7 @@ abstract class CategoryConverter extends ShopwareConverter protected string $oldCategoryId; - protected string $locale; + protected ?string $locale = null; protected string $runId; @@ -80,25 +79,16 @@ public function convert( $this->migrationContext = $migrationContext; $connection = $migrationContext->getConnection(); - $this->connectionId = ''; - $this->connectionName = ''; - if ($connection !== null) { - $this->connectionId = $connection->getId(); - $this->connectionName = $connection->getName(); - } + $this->connectionId = $connection->getId(); + $this->connectionName = $connection->getName(); - if (!isset($data['_locale'])) { - $this->loggingService->addLogEntry(new EmptyNecessaryFieldRunLog( - $migrationContext->getRunUuid(), - DefaultEntities::CATEGORY, - $this->oldCategoryId, - 'locale' - )); + $converted = []; - return new ConvertStruct(null, $data); + if (isset($data['_locale'])) { + $this->locale = $data['_locale']; + } else { + $this->locale = null; } - $this->locale = $data['_locale']; - $converted = []; $cmsPageUuid = $this->defaultCmsPageLookup->get($context); if ($cmsPageUuid !== null) { @@ -117,7 +107,7 @@ public function convert( throw MigrationException::parentEntityForChildNotFound(DefaultEntities::CATEGORY, $this->oldCategoryId); } $this->mappingIds[] = $parentMapping['id']; - $converted['parentId'] = $parentMapping['entityUuid']; + $converted['parentId'] = $parentMapping['entityId']; unset($parentMapping); // get last root category as previous sibling } elseif (!isset($data['previousSiblingId'])) { @@ -137,7 +127,7 @@ public function convert( ); if ($previousSiblingMapping !== null) { - $converted['afterCategoryId'] = $previousSiblingMapping['entityUuid']; + $converted['afterCategoryId'] = $previousSiblingMapping['entityId']; $this->mappingIds[] = $previousSiblingMapping['id']; } } @@ -151,7 +141,7 @@ public function convert( $this->checksum ); - $converted['id'] = $this->mainMapping['entityUuid']; + $converted['id'] = $this->mainMapping['entityId']; unset($data['id']); $this->convertValue($converted, 'description', $data, 'cmstext', self::TYPE_STRING); @@ -246,8 +236,7 @@ protected function setGivenCategoryTranslation(array &$data, array &$converted): } $locale = $language->getLocale(); - - if ($locale === null || $locale->getCode() === $data['_locale']) { + if (!isset($data['_locale']) || $locale?->getCode() === $data['_locale']) { return; } @@ -262,7 +251,7 @@ protected function setGivenCategoryTranslation(array &$data, array &$converted): $this->oldCategoryId . ':' . $data['_locale'], $this->context ); - $localeTranslation['id'] = $mapping['entityUuid']; + $localeTranslation['id'] = $mapping['entityId']; $this->mappingIds[] = $mapping['id']; try { @@ -299,7 +288,7 @@ protected function getCategoryMedia(array $media): array ); $categoryMedia = []; - $categoryMedia['id'] = $mapping['entityUuid']; + $categoryMedia['id'] = $mapping['entityId']; $this->mappingIds[] = $mapping['id']; if (empty($media['name'])) { @@ -329,7 +318,7 @@ protected function getCategoryMedia(array $media): array ); if ($albumMapping !== null) { - $categoryMedia['mediaFolderId'] = $albumMapping['entityUuid']; + $categoryMedia['mediaFolderId'] = $albumMapping['entityId']; $this->mappingIds[] = $albumMapping['id']; } @@ -363,13 +352,15 @@ protected function addMediaTranslation(array &$media, array $data): void $data['media']['id'] . ':' . $this->locale, $this->context ); - $localeTranslation['id'] = $mapping['entityUuid']; + $localeTranslation['id'] = $mapping['entityId']; $this->mappingIds[] = $mapping['id']; - $languageUuid = $this->languageLookup->get($this->locale, $this->context); - if ($languageUuid !== null) { - $localeTranslation['languageId'] = $languageUuid; - $media['translations'][$languageUuid] = $localeTranslation; + if ($this->locale !== null) { + $languageUuid = $this->languageLookup->get($this->locale, $this->context); + if ($languageUuid !== null) { + $localeTranslation['languageId'] = $languageUuid; + $media['translations'][$languageUuid] = $localeTranslation; + } } } } diff --git a/src/Profile/Shopware/Converter/CrossSellingConverter.php b/src/Profile/Shopware/Converter/CrossSellingConverter.php index 07c487f00..d4e202570 100644 --- a/src/Profile/Shopware/Converter/CrossSellingConverter.php +++ b/src/Profile/Shopware/Converter/CrossSellingConverter.php @@ -11,7 +11,6 @@ use Shopware\Core\Framework\Log\Package; use SwagMigrationAssistant\Migration\Converter\ConvertStruct; use SwagMigrationAssistant\Migration\DataSelection\DefaultEntities; -use SwagMigrationAssistant\Migration\Logging\Log\AssociationRequiredMissingLog; use SwagMigrationAssistant\Migration\MigrationContextInterface; #[Package('fundamentals@after-sales')] @@ -35,10 +34,7 @@ public function convert(array $data, Context $context, MigrationContextInterface $this->runId = $migrationContext->getRunUuid(); $connection = $migrationContext->getConnection(); - $this->connectionId = ''; - if ($connection !== null) { - $this->connectionId = $connection->getId(); - } + $this->connectionId = $connection->getId(); $converted = []; $this->mainMapping = $this->mappingService->getOrCreateMapping( @@ -57,33 +53,17 @@ public function convert(array $data, Context $context, MigrationContextInterface $this->checksum ); - $converted['id'] = $crossSellingMapping['entityUuid']; + $converted['id'] = $crossSellingMapping['entityId']; $sourceProductMapping = $this->getProductMapping($data['articleID']); - if ($sourceProductMapping === null) { - $this->loggingService->addLogEntry(new AssociationRequiredMissingLog( - $this->runId, - DefaultEntities::PRODUCT, - $data['articleID'], - $data['type'] - )); - - return new ConvertStruct(null, $data); + if ($sourceProductMapping !== null) { + $this->mappingIds[] = $sourceProductMapping['id']; } - $this->mappingIds[] = $sourceProductMapping['id']; $relatedProductMapping = $this->getProductMapping($data['relatedarticle']); - if ($relatedProductMapping === null) { - $this->loggingService->addLogEntry(new AssociationRequiredMissingLog( - $this->runId, - DefaultEntities::PRODUCT, - $data['relatedarticle'], - $data['type'] - )); - - return new ConvertStruct(null, $data); + if ($relatedProductMapping !== null) { + $this->mappingIds[] = $relatedProductMapping['id']; } - $this->mappingIds[] = $relatedProductMapping['id']; if ($data['type'] === DefaultEntities::CROSS_SELLING_SIMILAR) { $converted['name'] = 'Similar Items'; @@ -100,15 +80,17 @@ public function convert(array $data, Context $context, MigrationContextInterface $converted['type'] = 'productList'; $converted['active'] = true; - $converted['productId'] = $sourceProductMapping['entityUuid']; $converted['assignedProducts'] = [ [ - 'id' => $relationMapping['entityUuid'], - 'position' => $data['position'], - 'productId' => $relatedProductMapping['entityUuid'], + 'id' => $relationMapping['entityId'] ?? null, + 'position' => $data['position'] ?? null, + 'productId' => $relatedProductMapping['entityId'] ?? null, ], ]; + if (isset($sourceProductMapping['entityId'])) { + $converted['productId'] = $sourceProductMapping['entityId']; + } unset( $data['type'], $data['id'], diff --git a/src/Profile/Shopware/Converter/CurrencyConverter.php b/src/Profile/Shopware/Converter/CurrencyConverter.php index 46fb4df64..2a2b431d2 100644 --- a/src/Profile/Shopware/Converter/CurrencyConverter.php +++ b/src/Profile/Shopware/Converter/CurrencyConverter.php @@ -40,17 +40,14 @@ public function getSourceIdentifier(array $data): string return $data['currency']; } - public function convert(array $data, Context $context, MigrationContextInterface $migrationContext): ConvertStruct + public function convert(array $data, Context $context, MigrationContextInterface $migrationContext): ?ConvertStruct { $this->generateChecksum($data); $this->context = $context; $this->mainLocale = $data['_locale']; $connection = $migrationContext->getConnection(); - $this->connectionId = ''; - if ($connection !== null) { - $this->connectionId = $connection->getId(); - } + $this->connectionId = $connection->getId(); $currencyUuid = $this->currencyLookup->get($data['currency'], $context); if ($currencyUuid !== null) { @@ -77,7 +74,7 @@ public function convert(array $data, Context $context, MigrationContextInterface $context, $this->checksum ); - $converted['id'] = $this->mainMapping['entityUuid']; + $converted['id'] = $this->mainMapping['entityId']; $converted['isDefault'] = false; unset($data['standard']); @@ -137,7 +134,7 @@ protected function getCurrencyTranslation(array &$currency, array $data): void $data['id'] . ':' . $this->mainLocale, $this->context ); - $localeTranslation['id'] = $mapping['entityUuid']; + $localeTranslation['id'] = $mapping['entityId']; $this->mappingIds[] = $mapping['id']; $languageUuid = $this->languageLookup->get($this->mainLocale, $this->context); diff --git a/src/Profile/Shopware/Converter/CustomerConverter.php b/src/Profile/Shopware/Converter/CustomerConverter.php index 8698774eb..6964e59d8 100644 --- a/src/Profile/Shopware/Converter/CustomerConverter.php +++ b/src/Profile/Shopware/Converter/CustomerConverter.php @@ -7,6 +7,8 @@ namespace SwagMigrationAssistant\Profile\Shopware\Converter; +use Shopware\Core\Checkout\Customer\Aggregate\CustomerAddress\CustomerAddressDefinition; +use Shopware\Core\Checkout\Customer\CustomerDefinition; use Shopware\Core\Checkout\Customer\CustomerEntity; use Shopware\Core\Defaults; use Shopware\Core\Framework\Context; @@ -17,6 +19,7 @@ use Shopware\Core\System\SalesChannel\SalesChannelCollection; use SwagMigrationAssistant\Migration\Converter\ConvertStruct; use SwagMigrationAssistant\Migration\DataSelection\DefaultEntities; +use SwagMigrationAssistant\Migration\Logging\Log\Builder\MigrationLogBuilder; use SwagMigrationAssistant\Migration\Logging\Log\EmptyNecessaryFieldRunLog; use SwagMigrationAssistant\Migration\Logging\Log\FieldReassignedRunLog; use SwagMigrationAssistant\Migration\Logging\Log\UnknownEntityLog; @@ -26,10 +29,8 @@ use SwagMigrationAssistant\Migration\Mapping\Lookup\LanguageLookup; use SwagMigrationAssistant\Migration\Mapping\MappingServiceInterface; use SwagMigrationAssistant\Migration\MigrationContextInterface; -use SwagMigrationAssistant\Profile\Shopware\Logging\Log\InvalidEmailAddressLog; use SwagMigrationAssistant\Profile\Shopware\Premapping\PaymentMethodReader; use SwagMigrationAssistant\Profile\Shopware\Premapping\SalutationReader; -use Symfony\Component\Validator\Constraints\Email; use Symfony\Component\Validator\Validator\ValidatorInterface; #[Package('fundamentals@after-sales')] @@ -45,17 +46,6 @@ abstract class CustomerConverter extends ShopwareConverter protected string $runId; - /** - * @var list - */ - protected array $requiredDataFieldKeys = [ - 'firstname', - 'lastname', - 'email', - 'salutation', - 'customerGroupId', - ]; - /** * @var list */ @@ -96,46 +86,17 @@ public function convert( MigrationContextInterface $migrationContext, ): ConvertStruct { $this->generateChecksum($data); - $oldData = $data; $this->runId = $migrationContext->getRunUuid(); $this->migrationContext = $migrationContext; - $fields = $this->checkForEmptyRequiredDataFields($data, $this->requiredDataFieldKeys); - - if (!empty($fields)) { - $this->loggingService->addLogEntry(new EmptyNecessaryFieldRunLog( - $this->runId, - DefaultEntities::CUSTOMER, - $data['id'], - \implode(',', $fields) - )); - - return new ConvertStruct(null, $oldData); - } - - if (!$this->checkEmailValidity($data['email'])) { - $this->loggingService->addLogEntry(new InvalidEmailAddressLog( - $this->runId, - DefaultEntities::CUSTOMER, - $data['id'], - $data['email'] - )); - - return new ConvertStruct(null, $oldData); - } + $connection = $migrationContext->getConnection(); + $this->connectionId = $connection->getId(); + $this->connectionName = $connection->getName(); $this->context = $context; $this->mainLocale = $data['_locale']; unset($data['_locale']); - $connection = $migrationContext->getConnection(); - $this->connectionId = ''; - $this->connectionName = ''; - if ($connection !== null) { - $this->connectionId = $connection->getId(); - $this->connectionName = $connection->getName(); - } - $this->mainMapping = $this->mappingService->getOrCreateMapping( $this->connectionId, DefaultEntities::CUSTOMER, @@ -147,7 +108,7 @@ public function convert( $this->oldCustomerId = $data['id']; $converted = []; - $converted['id'] = $this->mainMapping['entityUuid']; + $converted['id'] = $this->mainMapping['entityId']; unset($data['id']); @@ -159,13 +120,13 @@ public function convert( $this->context ); - if (isset($mapping['entityUuid'])) { - $converted['salesChannelId'] = $mapping['entityUuid']; + if (isset($mapping['entityId'])) { + $converted['salesChannelId'] = $mapping['entityId']; $this->mappingIds[] = $mapping['id']; unset($data['subshopID']); if (isset($data['shop']['customer_scope']) && (bool) $data['shop']['customer_scope'] === true) { - $converted['boundSalesChannelId'] = $mapping['entityUuid']; + $converted['boundSalesChannelId'] = $mapping['entityId']; } } } @@ -203,28 +164,28 @@ public function convert( $converted['customerNumber'] = 'number-' . $this->oldCustomerId; } - $mapping = $this->mappingService->getMapping( - $this->connectionId, - DefaultEntities::CUSTOMER_GROUP, - $data['customerGroupId'], - $context - ); - if ($mapping === null) { - return new ConvertStruct(null, $oldData); + if (isset($data['customerGroupId'])) { + $mapping = $this->mappingService->getMapping( + $this->connectionId, + DefaultEntities::CUSTOMER_GROUP, + $data['customerGroupId'], + $context + ); + if ($mapping !== null) { + $converted['groupId'] = $mapping['entityId']; + $this->mappingIds[] = $mapping['id']; + } + unset($data['customerGroupId'], $data['customergroup']); } - $converted['groupId'] = $mapping['entityUuid']; - $this->mappingIds[] = $mapping['id']; - unset($data['customerGroupId'], $data['customergroup']); if (isset($data['defaultpayment']['id'])) { $defaultPaymentMethodUuid = $this->getDefaultPaymentMethod($data['defaultpayment']); - if ($defaultPaymentMethodUuid === null) { - return new ConvertStruct(null, $oldData); + if ($defaultPaymentMethodUuid !== null) { + $converted['defaultPaymentMethodId'] = $defaultPaymentMethodUuid; } - - $converted['defaultPaymentMethodId'] = $defaultPaymentMethodUuid; } + unset($data['defaultpayment'], $data['paymentpreset']); if (!isset($converted['defaultPaymentMethodId'])) { @@ -235,28 +196,19 @@ public function convert( $this->context ); - if ($mapping === null) { - $this->loggingService->addLogEntry(new EmptyNecessaryFieldRunLog( - $this->runId, - DefaultEntities::CUSTOMER, - $this->oldCustomerId, - 'defaultpayment' - )); - - return new ConvertStruct(null, $oldData); + if ($mapping !== null) { + $converted['defaultPaymentMethodId'] = $mapping['entityId']; + $this->mappingIds[] = $mapping['id']; } - $converted['defaultPaymentMethodId'] = $mapping['entityUuid']; - $this->mappingIds[] = $mapping['id']; } $salutationUuid = $this->getSalutation($data['salutation']); - if ($salutationUuid === null) { - return new ConvertStruct(null, $oldData); + if ($salutationUuid !== null) { + $converted['salutationId'] = $salutationUuid; } - $converted['salutationId'] = $salutationUuid; - if (isset($data['addresses']) && isset($this->mainMapping['entityUuid'])) { - $this->applyAddresses($data, $converted, $this->mainMapping['entityUuid']); + if (isset($data['addresses']) && isset($this->mainMapping['entityId'])) { + $this->applyAddresses($data, $converted, $this->mainMapping['entityId']); } if (isset($data['attributes'])) { @@ -295,19 +247,6 @@ public function convert( $returnData = null; } - if (!isset($converted['defaultBillingAddressId'], $converted['defaultShippingAddressId'])) { - $this->mappingService->deleteMapping($converted['id'], $this->connectionId, $this->context); - - $this->loggingService->addLogEntry(new EmptyNecessaryFieldRunLog( - $this->runId, - DefaultEntities::CUSTOMER, - $this->oldCustomerId, - 'address data' - )); - - return new ConvertStruct(null, $oldData); - } - $this->updateMainMapping($migrationContext, $context); return new ConvertStruct($converted, $returnData, $this->mainMapping['id'] ?? null); @@ -345,19 +284,20 @@ protected function getDefaultPaymentMethod(array $originalData): ?string ); if ($paymentMethodMapping === null) { - $this->loggingService->addLogEntry(new UnknownEntityLog( - $this->runId, - DefaultEntities::PAYMENT_METHOD, - $originalData['id'], - DefaultEntities::CUSTOMER, - $this->oldCustomerId - )); + $this->loggingService->addLogEntry( + MigrationLogBuilder::fromMigrationContext($this->migrationContext) + ->withEntityName(CustomerDefinition::ENTITY_NAME) + ->withFieldName('defaultPaymentMethodId') + ->withFieldSourcePath('default_payment_method') + ->withSourceData($originalData) + ->build(UnknownEntityLog::class) + ); return null; } $this->mappingIds[] = $paymentMethodMapping['id']; - return $paymentMethodMapping['entityUuid']; + return $paymentMethodMapping['entityId']; } /** @@ -373,12 +313,14 @@ protected function applyAddresses(array &$originalData, array &$converted, strin $fields = $this->checkForEmptyRequiredDataFields($address, $this->requiredAddressDataFieldKeys); if (!empty($fields)) { - $this->loggingService->addLogEntry(new EmptyNecessaryFieldRunLog( - $this->runId, - DefaultEntities::CUSTOMER_ADDRESS, - $address['id'], - \implode(',', $fields) - )); + $this->loggingService->addLogForEach( + $fields, + fn (string $key) => MigrationLogBuilder::fromMigrationContext($this->migrationContext) + ->withEntityName(CustomerAddressDefinition::ENTITY_NAME) + ->withFieldSourcePath($key) + ->withSourceData($address) + ->build(EmptyNecessaryFieldRunLog::class) + ); continue; } @@ -394,7 +336,7 @@ protected function applyAddresses(array &$originalData, array &$converted, strin $address['id'], $this->context ); - $newAddress['id'] = $addressMapping['entityUuid']; + $newAddress['id'] = $addressMapping['entityId']; $this->mappingIds[] = $addressMapping['id']; $newAddress['salutationId'] = $salutationUuid; @@ -414,11 +356,11 @@ protected function applyAddresses(array &$originalData, array &$converted, strin } } - if (!isset($this->mainMapping['entityUuid'])) { + if (!isset($this->mainMapping['entityId'])) { continue; } - $newAddress['customerId'] = $this->mainMapping['entityUuid']; + $newAddress['customerId'] = $this->mainMapping['entityId']; $newAddress['country'] = $this->getCountry($address['country']); $countryState = $this->getCountryState($address, $newAddress['country']['id']); @@ -456,13 +398,13 @@ protected function applyAddresses(array &$originalData, array &$converted, strin $converted['addresses'] = $addresses; // No valid default billing and shipping address was converted, so use the first valid one as default - $this->checkUnsetDefaultShippingAndDefaultBillingAddress($originalData, $converted, $customerUuid, $addresses); + $this->checkUnsetDefaultShippingAndDefaultBillingAddress($originalData, $converted, $addresses); // No valid default shipping address was converted, but the default billing address is valid - $this->checkUnsetDefaultShippingAddress($originalData, $converted, $customerUuid); + $this->checkUnsetDefaultShippingAddress($originalData, $converted); // No valid default billing address was converted, but the default shipping address is valid - $this->checkUnsetDefaultBillingAddress($originalData, $converted, $customerUuid); + $this->checkUnsetDefaultBillingAddress($originalData, $converted); } /** @@ -487,7 +429,7 @@ protected function getCountry(array $oldCountryData): array $oldCountryData['id'], $this->context ); - $country['id'] = $mapping['entityUuid']; + $country['id'] = $mapping['entityId']; $this->mappingIds[] = $mapping['id']; } @@ -533,7 +475,7 @@ protected function applyCountryTranslation(array &$country, array $data): void $data['id'] . ':' . $this->mainLocale, $this->context ); - $localeTranslation['id'] = $mapping['entityUuid']; + $localeTranslation['id'] = $mapping['entityId']; $this->mappingIds[] = $mapping['id']; $languageUuid = $this->languageLookup->get($this->mainLocale, $this->context); @@ -558,13 +500,12 @@ protected function getCountryState(array $oldAddressData, string $newCountryId): if (!isset($oldAddressData['state_id'], $oldAddressData['country']['countryiso'], $oldAddressData['state']['shortcode'])) { $this->loggingService->addLogEntry( - new UnknownEntityLog( - $this->runId, - DefaultEntities::COUNTRY_STATE, - $oldAddressData['state_id'] ?? 'unknown', - DefaultEntities::CUSTOMER, - $this->oldCustomerId - ) + MigrationLogBuilder::fromMigrationContext($this->migrationContext) + ->withEntityName(CustomerAddressDefinition::ENTITY_NAME) + ->withFieldName('stateId') + ->withFieldSourcePath('state_id') + ->withSourceData($oldAddressData) + ->build(UnknownEntityLog::class) ); return []; @@ -596,19 +537,18 @@ protected function getCountryState(array $oldAddressData, string $newCountryId): $oldAddressData['state']['active'] )) { $this->loggingService->addLogEntry( - new UnknownEntityLog( - $this->runId, - DefaultEntities::COUNTRY_STATE, - $oldAddressData['state_id'], - DefaultEntities::CUSTOMER, - $this->oldCustomerId - ) + MigrationLogBuilder::fromMigrationContext($this->migrationContext) + ->withEntityName(CustomerAddressDefinition::ENTITY_NAME) + ->withFieldName('stateId') + ->withFieldSourcePath('state.name') + ->withSourceData($oldAddressData['state']) + ->build(UnknownEntityLog::class) ); return []; } - $state['id'] = $mapping['entityUuid']; + $state['id'] = $mapping['entityId']; $this->mappingIds[] = $mapping['id']; $oldStateData = $oldAddressData['state']; @@ -649,7 +589,7 @@ protected function applyCountryStateTranslation(array &$state, array $data): voi $data['id'] . ':' . $this->mainLocale, $this->context ); - $localeTranslation['id'] = $mapping['entityUuid']; + $localeTranslation['id'] = $mapping['entityId']; $this->mappingIds[] = $mapping['id']; $languageUuid = $this->languageLookup->get($this->mainLocale, $this->context); @@ -664,20 +604,25 @@ protected function applyCountryStateTranslation(array &$state, array $data): voi * @param array $converted * @param array> $addresses */ - protected function checkUnsetDefaultShippingAndDefaultBillingAddress(array &$originalData, array &$converted, string $customerUuid, array $addresses): void + protected function checkUnsetDefaultShippingAndDefaultBillingAddress(array &$originalData, array &$converted, array $addresses): void { if (!isset($converted['defaultBillingAddressId']) && !isset($converted['defaultShippingAddressId'])) { $converted['defaultBillingAddressId'] = $addresses[0]['id']; $converted['defaultShippingAddressId'] = $addresses[0]['id']; unset($originalData['default_billing_address_id'], $originalData['default_shipping_address_id']); - $this->loggingService->addLogEntry(new FieldReassignedRunLog( - $this->runId, - DefaultEntities::CUSTOMER, - $customerUuid, - 'default billing and shipping address', - 'first address' - )); + $this->loggingService->addLogForEach( + [ + 'defaultBillingAddressId' => 'default_billing_address_id', + 'defaultShippingAddressId' => 'default_shipping_address_id', + ], + fn (string $key, string $value) => MigrationLogBuilder::fromMigrationContext($this->migrationContext) + ->withEntityName(CustomerAddressDefinition::ENTITY_NAME) + ->withFieldName($key) + ->withFieldSourcePath($value) + ->withSourceData($originalData) + ->build(FieldReassignedRunLog::class) + ); } } @@ -685,19 +630,20 @@ protected function checkUnsetDefaultShippingAndDefaultBillingAddress(array &$ori * @param array $originalData * @param array $converted */ - protected function checkUnsetDefaultShippingAddress(array &$originalData, array &$converted, string $customerUuid): void + protected function checkUnsetDefaultShippingAddress(array &$originalData, array &$converted): void { if (!isset($converted['defaultShippingAddressId']) && isset($converted['defaultBillingAddressId'])) { $converted['defaultShippingAddressId'] = $converted['defaultBillingAddressId']; unset($originalData['default_shipping_address_id']); - $this->loggingService->addLogEntry(new FieldReassignedRunLog( - $this->runId, - DefaultEntities::CUSTOMER, - $customerUuid, - 'default shipping address', - 'default billing address' - )); + $this->loggingService->addLogEntry( + MigrationLogBuilder::fromMigrationContext($this->migrationContext) + ->withEntityName(CustomerAddressDefinition::ENTITY_NAME) + ->withFieldName('defaultShippingAddressId') + ->withFieldSourcePath('default_shipping_address_id') + ->withSourceData($originalData) + ->build(FieldReassignedRunLog::class) + ); } } @@ -705,19 +651,20 @@ protected function checkUnsetDefaultShippingAddress(array &$originalData, array * @param array $originalData * @param array $converted */ - protected function checkUnsetDefaultBillingAddress(array &$originalData, array &$converted, string $customerUuid): void + protected function checkUnsetDefaultBillingAddress(array &$originalData, array &$converted): void { if (!isset($converted['defaultBillingAddressId']) && isset($converted['defaultShippingAddressId'])) { $converted['defaultBillingAddressId'] = $converted['defaultShippingAddressId']; unset($originalData['default_billing_address_id']); - $this->loggingService->addLogEntry(new FieldReassignedRunLog( - $this->runId, - DefaultEntities::CUSTOMER, - $customerUuid, - 'default billing address', - 'default shipping address' - )); + $this->loggingService->addLogEntry( + MigrationLogBuilder::fromMigrationContext($this->migrationContext) + ->withEntityName(CustomerAddressDefinition::ENTITY_NAME) + ->withFieldName('defaultBillingAddressId') + ->withFieldSourcePath('default_billing_address_id') + ->withSourceData($originalData) + ->build(FieldReassignedRunLog::class) + ); } } @@ -731,30 +678,20 @@ protected function getSalutation(string $salutation): ?string ); if ($mapping === null) { - $this->loggingService->addLogEntry(new UnknownEntityLog( - $this->runId, - DefaultEntities::SALUTATION, - $salutation, - DefaultEntities::CUSTOMER, - $this->oldCustomerId - )); + $this->loggingService->addLogEntry( + MigrationLogBuilder::fromMigrationContext($this->migrationContext) + ->withEntityName(CustomerDefinition::ENTITY_NAME) + ->withFieldName('salutationId') + ->withFieldSourcePath('salutation') + ->withSourceData(['salutation' => $salutation]) + ->build(UnknownEntityLog::class) + ); return null; } $this->mappingIds[] = $mapping['id']; - return $mapping['entityUuid']; - } - - protected function checkEmailValidity(string $email): bool - { - $constraint = new Email(); - $errors = $this->validator->validate( - $email, - $constraint - ); - - return \count($errors) === 0; + return $mapping['entityId']; } /** diff --git a/src/Profile/Shopware/Converter/CustomerGroupConverter.php b/src/Profile/Shopware/Converter/CustomerGroupConverter.php index b77dcc163..4d0bd165c 100644 --- a/src/Profile/Shopware/Converter/CustomerGroupConverter.php +++ b/src/Profile/Shopware/Converter/CustomerGroupConverter.php @@ -44,12 +44,8 @@ public function convert(array $data, Context $context, MigrationContextInterface unset($data['_locale']); $connection = $migrationContext->getConnection(); - $this->connectionId = ''; - $this->connectionName = ''; - if ($connection !== null) { - $this->connectionId = $connection->getId(); - $this->connectionName = $connection->getName(); - } + $this->connectionId = $connection->getId(); + $this->connectionName = $connection->getName(); $this->mainMapping = $this->mappingService->getOrCreateMapping( $this->connectionId, @@ -60,7 +56,7 @@ public function convert(array $data, Context $context, MigrationContextInterface ); $converted = []; - $converted['id'] = $this->mainMapping['entityUuid']; + $converted['id'] = $this->mainMapping['entityId']; if (isset($data['attributes'])) { $converted['customFields'] = $this->getAttributes($data['attributes'], DefaultEntities::CUSTOMER_GROUP, $this->connectionName, ['id', 'customerGroupID'], $this->context); @@ -109,7 +105,7 @@ public function getCustomerGroupTranslation(array &$customerGroup, array $data): $data['id'] . ':' . $this->locale, $this->context ); - $localeTranslation['id'] = $mapping['entityUuid']; + $localeTranslation['id'] = $mapping['entityId']; $this->mappingIds[] = $mapping['id']; $languageUuid = $this->languageLookup->get($this->locale, $this->context); diff --git a/src/Profile/Shopware/Converter/CustomerWishlistConverter.php b/src/Profile/Shopware/Converter/CustomerWishlistConverter.php index 516cb3dba..7bcbe3261 100644 --- a/src/Profile/Shopware/Converter/CustomerWishlistConverter.php +++ b/src/Profile/Shopware/Converter/CustomerWishlistConverter.php @@ -27,10 +27,7 @@ public function convert(array $data, Context $context, MigrationContextInterface $this->migrationContext = $migrationContext; $connection = $migrationContext->getConnection(); - $this->connectionId = ''; - if ($connection !== null) { - $this->connectionId = $connection->getId(); - } + $this->connectionId = $connection->getId(); $this->mainMapping = $this->mappingService->getOrCreateMapping( $this->connectionId, @@ -40,31 +37,31 @@ public function convert(array $data, Context $context, MigrationContextInterface $this->checksum ); + $converted = []; + $customerMapping = $this->mappingService->getMapping($this->connectionId, DefaultEntities::CUSTOMER, $data['userID'], $context); - if ($customerMapping === null) { - return new ConvertStruct(null, $data); + if ($customerMapping !== null) { + $this->mappingIds[] = $customerMapping['id']; + $converted['customerId'] = $customerMapping['entityId']; } + $productId = null; $productMapping = $this->mappingService->getMapping($this->connectionId, DefaultEntities::PRODUCT, $data['ordernumber'], $context); - if ($productMapping === null) { - return new ConvertStruct(null, $data); + if ($productMapping !== null) { + $this->mappingIds[] = $productMapping['id']; + $productId = $productMapping['entityId']; } $shopMapping = $this->mappingService->getMapping($this->connectionId, DefaultEntities::SALES_CHANNEL, $data['subshopID'], $context); - if ($shopMapping === null) { - return new ConvertStruct(null, $data); + if ($shopMapping !== null) { + $converted['salesChannelId'] = $shopMapping['entityId']; } - $this->mappingIds[] = $customerMapping['id']; - $this->mappingIds[] = $productMapping['id']; + $converted['id'] = $this->mainMapping['entityId']; - $converted = []; - $converted['id'] = $this->mainMapping['entityUuid']; - $converted['customerId'] = $customerMapping['entityUuid']; - $converted['salesChannelId'] = $shopMapping['entityUuid']; $converted['products'][] = [ - 'id' => $this->mappingService->getOrCreateMapping($this->connectionId, DefaultEntities::CUSTOMER_WISHLIST_PRODUCT, $data['userID'] . '_' . $data['ordernumber'], $context)['entityUuid'], - 'productId' => $productMapping['entityUuid'], + 'id' => $this->mappingService->getOrCreateMapping($this->connectionId, DefaultEntities::CUSTOMER_WISHLIST_PRODUCT, $data['userID'] . '_' . $data['ordernumber'], $context)['entityId'], + 'productId' => $productId, ]; $this->updateMainMapping($migrationContext, $context); diff --git a/src/Profile/Shopware/Converter/LanguageConverter.php b/src/Profile/Shopware/Converter/LanguageConverter.php index c35293ab4..d0732d893 100644 --- a/src/Profile/Shopware/Converter/LanguageConverter.php +++ b/src/Profile/Shopware/Converter/LanguageConverter.php @@ -11,7 +11,6 @@ use Shopware\Core\Framework\Log\Package; use SwagMigrationAssistant\Migration\Converter\ConvertStruct; use SwagMigrationAssistant\Migration\DataSelection\DefaultEntities; -use SwagMigrationAssistant\Migration\Logging\Log\EntityAlreadyExistsRunLog; use SwagMigrationAssistant\Migration\Logging\LoggingServiceInterface; use SwagMigrationAssistant\Migration\Mapping\Lookup\LanguageLookup; use SwagMigrationAssistant\Migration\Mapping\Lookup\LocaleLookup; @@ -28,8 +27,8 @@ abstract class LanguageConverter extends ShopwareConverter public function __construct( MappingServiceInterface $mappingService, LoggingServiceInterface $loggingService, - protected readonly LanguageLookup $languageLookup, protected readonly LocaleLookup $localeLookup, + protected readonly LanguageLookup $languageLookup, ) { parent::__construct($mappingService, $loggingService); } @@ -39,26 +38,17 @@ public function getSourceIdentifier(array $data): string return $data['locale']; } - public function convert(array $data, Context $context, MigrationContextInterface $migrationContext): ConvertStruct + public function convert(array $data, Context $context, MigrationContextInterface $migrationContext): ?ConvertStruct { $this->generateChecksum($data); $this->context = $context; $connection = $migrationContext->getConnection(); - $this->connectionId = ''; - if ($connection !== null) { - $this->connectionId = $connection->getId(); - } + $this->connectionId = $connection->getId(); $languageUuid = $this->languageLookup->get($data['locale'], $context); if ($languageUuid !== null) { - $this->loggingService->addLogEntry(new EntityAlreadyExistsRunLog( - $migrationContext->getRunUuid(), - DefaultEntities::LANGUAGE, - $data['id'] - )); - - return new ConvertStruct(null, $data); + return null; } $converted = []; @@ -69,7 +59,7 @@ public function convert(array $data, Context $context, MigrationContextInterface $context, $this->checksum ); - $converted['id'] = $this->mainMapping['entityUuid']; + $converted['id'] = $this->mainMapping['entityId']; $this->convertValue($converted, 'name', $data, 'language'); diff --git a/src/Profile/Shopware/Converter/MainVariantRelationConverter.php b/src/Profile/Shopware/Converter/MainVariantRelationConverter.php index f6bfcfe79..17748310b 100644 --- a/src/Profile/Shopware/Converter/MainVariantRelationConverter.php +++ b/src/Profile/Shopware/Converter/MainVariantRelationConverter.php @@ -11,7 +11,8 @@ use Shopware\Core\Framework\Log\Package; use SwagMigrationAssistant\Migration\Converter\ConvertStruct; use SwagMigrationAssistant\Migration\DataSelection\DefaultEntities; -use SwagMigrationAssistant\Migration\Logging\Log\AssociationRequiredMissingLog; +use SwagMigrationAssistant\Migration\Logging\Log\Builder\MigrationLogBuilder; +use SwagMigrationAssistant\Migration\Logging\Log\MainVariantRelationNotConverted; use SwagMigrationAssistant\Migration\MigrationContextInterface; #[Package('fundamentals@after-sales')] @@ -21,25 +22,28 @@ abstract class MainVariantRelationConverter extends ShopwareConverter protected string $connectionId = ''; - private string $runUuid; - public function getSourceIdentifier(array $data): string { return $data['id']; } - public function convert(array $data, Context $context, MigrationContextInterface $migrationContext): ConvertStruct + public function convert(array $data, Context $context, MigrationContextInterface $migrationContext): ?ConvertStruct { $this->generateChecksum($data); $this->context = $context; - $this->runUuid = $migrationContext->getRunUuid(); $connection = $migrationContext->getConnection(); - if ($connection !== null) { - $this->connectionId = $connection->getId(); - } + $this->connectionId = $connection->getId(); if (!isset($data['id'], $data['ordernumber'])) { - return new ConvertStruct(null, $data); + $this->loggingService->addLogEntry( + MigrationLogBuilder::fromMigrationContext($migrationContext) + ->withSourceData($data) + ->withExceptionMessage('MainVariantRelation requires ID and order number, to be converted successful') + ->withExceptionTrace(\debug_backtrace(\DEBUG_BACKTRACE_IGNORE_ARGS, 2)) + ->build(MainVariantRelationNotConverted::class) + ); + + return null; } $this->mainMapping = $this->mappingService->getOrCreateMapping( @@ -64,28 +68,21 @@ public function convert(array $data, Context $context, MigrationContextInterface $context ); - if ($mainProductMapping === null) { - $this->addAssociationRequiredLog(DefaultEntities::PRODUCT_CONTAINER, $data['id']); + $converted = []; - return new ConvertStruct(null, $data); + if ($mainProductMapping !== null) { + $this->mappingIds[] = $mainProductMapping['id']; + $converted['id'] = $mainProductMapping['entityId']; } - if ($variantProductMapping === null) { - $this->addAssociationRequiredLog(DefaultEntities::PRODUCT, $data['ordernumber']); - - return new ConvertStruct(null, $data); + if ($variantProductMapping !== null) { + $this->mappingIds[] = $variantProductMapping['id']; + $converted['variantListingConfig'] = [ + 'displayParent' => true, + 'mainVariantId' => $variantProductMapping['entityId'], + ]; } - $this->mappingIds[] = $mainProductMapping['id']; - $this->mappingIds[] = $variantProductMapping['id']; - - $converted = []; - $converted['id'] = $mainProductMapping['entityUuid']; - - $converted['variantListingConfig'] = [ - 'displayParent' => true, - 'mainVariantId' => $variantProductMapping['entityUuid'], - ]; unset($data['id'], $data['ordernumber']); $returnData = $data; @@ -97,16 +94,4 @@ public function convert(array $data, Context $context, MigrationContextInterface return new ConvertStruct($converted, $returnData, $this->mainMapping['id'] ?? null); } - - private function addAssociationRequiredLog(string $requiredEntity, string $id): void - { - $this->loggingService->addLogEntry( - new AssociationRequiredMissingLog( - $this->runUuid, - $requiredEntity, - $id, - DefaultEntities::MAIN_VARIANT_RELATION - ) - ); - } } diff --git a/src/Profile/Shopware/Converter/MediaConverter.php b/src/Profile/Shopware/Converter/MediaConverter.php index c7285189e..8ad55bbb6 100644 --- a/src/Profile/Shopware/Converter/MediaConverter.php +++ b/src/Profile/Shopware/Converter/MediaConverter.php @@ -57,10 +57,7 @@ public function convert( unset($data['_locale']); $connection = $migrationContext->getConnection(); - $this->connectionId = ''; - if ($connection !== null) { - $this->connectionId = $connection->getId(); - } + $this->connectionId = $connection->getId(); $converted = []; $this->mainMapping = $this->mappingService->getOrCreateMapping( @@ -70,7 +67,7 @@ public function convert( $context, $this->checksum ); - $converted['id'] = $this->mainMapping['entityUuid']; + $converted['id'] = $this->mainMapping['entityId']; if (empty($data['name'])) { $data['name'] = $converted['id']; @@ -100,7 +97,7 @@ public function convert( ); if ($albumMapping !== null) { - $converted['mediaFolderId'] = $albumMapping['entityUuid']; + $converted['mediaFolderId'] = $albumMapping['entityId']; $this->mappingIds[] = $albumMapping['id']; } @@ -151,7 +148,7 @@ protected function getMediaTranslation(array &$media, array $data): void $data['id'] . ':' . $this->locale, $this->context ); - $localeTranslation['id'] = $mapping['entityUuid']; + $localeTranslation['id'] = $mapping['entityId']; $this->mappingIds[] = $mapping['id']; $languageUuid = $this->languageLookup->get($this->locale, $this->context); diff --git a/src/Profile/Shopware/Converter/MediaFolderConverter.php b/src/Profile/Shopware/Converter/MediaFolderConverter.php index 30b4bdb25..ab8cde69a 100644 --- a/src/Profile/Shopware/Converter/MediaFolderConverter.php +++ b/src/Profile/Shopware/Converter/MediaFolderConverter.php @@ -50,10 +50,7 @@ public function convert(array $data, Context $context, MigrationContextInterface unset($data['_locale']); $connection = $migrationContext->getConnection(); - $this->connectionId = ''; - if ($connection !== null) { - $this->connectionId = $connection->getId(); - } + $this->connectionId = $connection->getId(); $converted = []; $this->mainMapping = $this->mappingService->getOrCreateMapping( @@ -63,7 +60,7 @@ public function convert(array $data, Context $context, MigrationContextInterface $this->context, $this->checksum ); - $converted['id'] = $this->mainMapping['entityUuid']; + $converted['id'] = $this->mainMapping['entityId']; unset($data['id']); $defaultFolderId = $this->getDefaultFolderId(); @@ -80,7 +77,7 @@ public function convert(array $data, Context $context, MigrationContextInterface ); if ($parentMapping !== null) { - $converted['parentId'] = $parentMapping['entityUuid']; + $converted['parentId'] = $parentMapping['entityId']; $this->mappingIds[] = $parentMapping['id']; } unset($parentMapping); @@ -104,10 +101,10 @@ public function convert(array $data, Context $context, MigrationContextInterface $this->mappingIds[] = $configurationMapping['id']; $converted['parent'] = [ - 'id' => $parentMapping['entityUuid'], + 'id' => $parentMapping['entityId'], 'name' => 'Migration media folder', 'configuration' => [ - 'id' => $configurationMapping['entityUuid'], + 'id' => $configurationMapping['entityId'], ], ]; } @@ -151,7 +148,7 @@ protected function getConfiguration(array &$setting, MigrationContextInterface $ $setting['id'], $this->context ); - $configuration['id'] = $mapping['entityUuid']; + $configuration['id'] = $mapping['entityId']; $this->mappingIds[] = $mapping['id']; $this->convertValue($configuration, 'createThumbnails', $setting, 'create_thumbnails', self::TYPE_BOOLEAN); @@ -176,7 +173,7 @@ protected function getConfiguration(array &$setting, MigrationContextInterface $ $thumbnailSize['width'] . '-' . $thumbnailSize['height'], $this->context ); - $uuid = $mapping['entityUuid']; + $uuid = $mapping['entityId']; $this->mappingIds[] = $mapping['id']; } diff --git a/src/Profile/Shopware/Converter/NewsletterRecipientConverter.php b/src/Profile/Shopware/Converter/NewsletterRecipientConverter.php index adc1fe172..6b97460bb 100644 --- a/src/Profile/Shopware/Converter/NewsletterRecipientConverter.php +++ b/src/Profile/Shopware/Converter/NewsletterRecipientConverter.php @@ -7,11 +7,13 @@ namespace SwagMigrationAssistant\Profile\Shopware\Converter; +use Shopware\Core\Content\Newsletter\Aggregate\NewsletterRecipient\NewsletterRecipientDefinition; use Shopware\Core\Framework\Context; use Shopware\Core\Framework\Log\Package; use Shopware\Core\Framework\Uuid\Uuid; use SwagMigrationAssistant\Migration\Converter\ConvertStruct; use SwagMigrationAssistant\Migration\DataSelection\DefaultEntities; +use SwagMigrationAssistant\Migration\Logging\Log\Builder\MigrationLogBuilder; use SwagMigrationAssistant\Migration\Logging\Log\EmptyNecessaryFieldRunLog; use SwagMigrationAssistant\Migration\Logging\Log\UnknownEntityLog; use SwagMigrationAssistant\Migration\Logging\LoggingServiceInterface; @@ -34,14 +36,6 @@ abstract class NewsletterRecipientConverter extends ShopwareConverter protected string $runId; - /** - * @var list - */ - protected array $requiredDataFieldKeys = [ - '_locale', - 'shopId', - ]; - public function __construct( MappingServiceInterface $mappingService, LoggingServiceInterface $loggingService, @@ -55,31 +49,16 @@ public function convert( Context $context, MigrationContextInterface $migrationContext, ): ConvertStruct { - $this->runId = $migrationContext->getRunUuid(); - $fields = $this->checkForEmptyRequiredDataFields($data, $this->requiredDataFieldKeys); + $connection = $migrationContext->getConnection(); + $this->connectionId = $connection->getId(); - if (!empty($fields)) { - $this->loggingService->addLogEntry(new EmptyNecessaryFieldRunLog( - $this->runId, - DefaultEntities::NEWSLETTER_RECIPIENT, - $data['id'], - \implode(',', $fields) - )); + $this->runId = $migrationContext->getRunUuid(); - return new ConvertStruct(null, $data); - } - $oldData = $data; $this->generateChecksum($data); $this->context = $context; $this->locale = $data['_locale']; unset($data['_locale']); - $connection = $migrationContext->getConnection(); - $this->connectionId = ''; - if ($connection !== null) { - $this->connectionId = $connection->getId(); - } - $converted = []; $this->oldNewsletterRecipientId = $data['id']; $this->mainMapping = $this->mappingService->getOrCreateMapping( @@ -89,7 +68,7 @@ public function convert( $context, $this->checksum ); - $converted['id'] = $this->mainMapping['entityUuid']; + $converted['id'] = $this->mainMapping['entityId']; $this->convertValue($converted, 'email', $data, 'email'); $this->convertValue($converted, 'createdAt', $data, 'added', 'datetime'); @@ -104,7 +83,7 @@ public function convert( $this->convertValue($converted, 'city', $address, 'city'); if (isset($address['salutation'])) { - $salutationUuid = $this->getSalutation($address['salutation']); + $salutationUuid = $this->getSalutation($address['salutation'], $migrationContext); if ($salutationUuid !== null) { $converted['salutationId'] = $salutationUuid; } @@ -116,24 +95,22 @@ public function convert( if (isset($converted['confirmedAt'])) { $status = 'optIn'; } else { - $status = $this->getStatus(); + $status = $this->getStatus($migrationContext); } - if ($status === null) { - return new ConvertStruct(null, $oldData); + if ($status !== null) { + $converted['status'] = $status; } - $converted['status'] = $status; $converted['languageId'] = $this->languageLookup->get($this->locale, $context); $salesChannelUuid = $this->getSalesChannel($data); - if ($salesChannelUuid === null) { - return new ConvertStruct(null, $oldData); + if ($salesChannelUuid !== null) { + $converted['salesChannelId'] = $salesChannelUuid; } - unset($data['shopId']); - $converted['salesChannelId'] = $salesChannelUuid; unset( + $data['shopId'], $data['id'], $data['groupID'], $data['lastmailing'], @@ -150,7 +127,7 @@ public function convert( return new ConvertStruct($converted, $returnData, $this->mainMapping['id'] ?? null); } - protected function getSalutation(string $salutation): ?string + protected function getSalutation(string $salutation, MigrationContextInterface $migrationContext): ?string { $salutationMapping = $this->mappingService->getMapping( $this->connectionId, @@ -160,19 +137,19 @@ protected function getSalutation(string $salutation): ?string ); if ($salutationMapping === null) { - $this->loggingService->addLogEntry(new UnknownEntityLog( - $this->runId, - 'salutation', - $salutation, - DefaultEntities::NEWSLETTER_RECIPIENT, - $this->oldNewsletterRecipientId - )); + $this->loggingService->addLogEntry( + MigrationLogBuilder::fromMigrationContext($migrationContext) + ->withEntityName(NewsletterRecipientDefinition::ENTITY_NAME) + ->withFieldName('salutationId') + ->withSourceData(['salutation' => $salutation]) + ->build(UnknownEntityLog::class) + ); return null; } $this->mappingIds[] = $salutationMapping['id']; - return $salutationMapping['entityUuid']; + return $salutationMapping['entityId']; } /** @@ -190,21 +167,23 @@ protected function getSalesChannel(array $data): ?string } if (!isset($salesChannelMapping)) { - $this->loggingService->addLogEntry(new EmptyNecessaryFieldRunLog( - $this->runId, - DefaultEntities::NEWSLETTER_RECIPIENT, - $this->oldNewsletterRecipientId, - 'salesChannel' - )); + $this->loggingService->addLogEntry( + MigrationLogBuilder::fromMigrationContext($this->migrationContext) + ->withEntityName(NewsletterRecipientDefinition::ENTITY_NAME) + ->withFieldName('salesChannelId') + ->withFieldSourcePath('shopId') + ->withSourceData($data) + ->build(EmptyNecessaryFieldRunLog::class) + ); return null; } $this->mappingIds[] = $salesChannelMapping['id']; - return $salesChannelMapping['entityUuid']; + return $salesChannelMapping['entityId']; } - protected function getStatus(): ?string + protected function getStatus(MigrationContextInterface $migrationContext): ?string { $status = $this->mappingService->getValue( $this->connectionId, @@ -214,12 +193,13 @@ protected function getStatus(): ?string ); if ($status === null) { - $this->loggingService->addLogEntry(new EmptyNecessaryFieldRunLog( - $this->runId, - DefaultEntities::NEWSLETTER_RECIPIENT, - $this->oldNewsletterRecipientId, - 'status' - )); + $this->loggingService->addLogEntry( + MigrationLogBuilder::fromMigrationContext($migrationContext) + ->withEntityName(NewsletterRecipientDefinition::ENTITY_NAME) + ->withFieldName('status') + ->withSourceData(['status' => NewsletterRecipientStatusReader::SOURCE_ID]) + ->build(EmptyNecessaryFieldRunLog::class) + ); } return $status; diff --git a/src/Profile/Shopware/Converter/NumberRangeConverter.php b/src/Profile/Shopware/Converter/NumberRangeConverter.php index 6809c65d0..8ca84d57b 100644 --- a/src/Profile/Shopware/Converter/NumberRangeConverter.php +++ b/src/Profile/Shopware/Converter/NumberRangeConverter.php @@ -17,13 +17,11 @@ use Shopware\Core\System\NumberRange\NumberRangeEntity; use SwagMigrationAssistant\Migration\Converter\ConvertStruct; use SwagMigrationAssistant\Migration\DataSelection\DefaultEntities; -use SwagMigrationAssistant\Migration\Logging\Log\EmptyNecessaryFieldRunLog; use SwagMigrationAssistant\Migration\Logging\LoggingServiceInterface; use SwagMigrationAssistant\Migration\Mapping\Lookup\LanguageLookup; use SwagMigrationAssistant\Migration\Mapping\Lookup\NumberRangeLookup; use SwagMigrationAssistant\Migration\Mapping\MappingServiceInterface; use SwagMigrationAssistant\Migration\MigrationContextInterface; -use SwagMigrationAssistant\Profile\Shopware\Logging\Log\UnsupportedNumberRangeTypeLog; #[Package('fundamentals@after-sales')] abstract class NumberRangeConverter extends ShopwareConverter @@ -67,38 +65,12 @@ public function convert(array $data, Context $context, MigrationContextInterface $this->numberRangeTypes = $this->numberRangeTypeRepo->search(new Criteria(), $context)->getEntities(); } - if (!\array_key_exists($data['name'], self::TYPE_MAPPING)) { - $this->loggingService->addLogEntry( - new UnsupportedNumberRangeTypeLog( - $migrationContext->getRunUuid(), - DefaultEntities::NUMBER_RANGE, - $data['id'], - $data['name'] - ) - ); - - return new ConvertStruct(null, $data); - } - $connection = $migrationContext->getConnection(); - if ($connection === null) { - return new ConvertStruct(null, $data); - } $this->connectionId = $connection->getId(); - $converted = []; $converted['id'] = $this->getUuid($data, $migrationContext, $context); - $converted['typeId'] = $this->getProductNumberRangeTypeUuid($data['name']); - - if (empty($converted['typeId'])) { - $this->loggingService->addLogEntry(new EmptyNecessaryFieldRunLog( - $migrationContext->getRunUuid(), - DefaultEntities::NUMBER_RANGE, - $data['id'], - 'typeId' - )); - - return new ConvertStruct(null, $data); + if (\array_key_exists($data['name'], self::TYPE_MAPPING)) { + $converted['typeId'] = $this->getProductNumberRangeTypeUuid($data['name']); } $converted['global'] = $this->getGlobal($data['name']); @@ -152,7 +124,7 @@ protected function getUuid(array $data, MigrationContextInterface $migrationCont if ($mapping !== null) { $this->mainMapping = $mapping; - return (string) $mapping['entityUuid']; + return (string) $mapping['entityId']; } // use global number range uuid for products if available @@ -168,7 +140,7 @@ protected function getUuid(array $data, MigrationContextInterface $migrationCont 'connectionId' => $this->connectionId, 'entity' => DefaultEntities::NUMBER_RANGE, 'oldIdentifier' => $data['id'], - 'entityUuid' => $productNumberRageUuid, + 'entityId' => $productNumberRageUuid, 'checksum' => null, 'entityValue' => null, 'additionalData' => null, @@ -186,7 +158,7 @@ protected function getUuid(array $data, MigrationContextInterface $migrationCont $this->checksum ); - return (string) $this->mainMapping['entityUuid']; + return (string) $this->mainMapping['entityId']; } protected function getProductNumberRangeTypeUuid(string $type): ?string @@ -239,7 +211,7 @@ protected function setNumberRangeTranslation( $data['id'] . ':' . $data['_locale'], $context ); - $localeTranslation['id'] = $mapping['entityUuid']; + $localeTranslation['id'] = $mapping['entityId']; $languageUuid = $this->languageLookup->get($data['_locale'], $context); if ($languageUuid !== null) { @@ -264,10 +236,10 @@ protected function setNumberRangeSalesChannels(array &$converted, Context $conte $context ); $numberRangeSalesChannel = []; - $numberRangeSalesChannel['id'] = $mapping['entityUuid']; + $numberRangeSalesChannel['id'] = $mapping['entityId']; $numberRangeSalesChannel['numberRangeId'] = $converted['id']; $numberRangeSalesChannel['salesChannelId'] = $saleChannelId; - $numberRangeSalesChannel['numberRangeTypeId'] = $converted['typeId']; + $numberRangeSalesChannel['numberRangeTypeId'] = $converted['typeId'] ?? null; $numberRangeSalesChannels[] = $numberRangeSalesChannel; $this->mappingIds[] = $mapping['id']; } diff --git a/src/Profile/Shopware/Converter/OrderConverter.php b/src/Profile/Shopware/Converter/OrderConverter.php index 07c528830..927b74a18 100644 --- a/src/Profile/Shopware/Converter/OrderConverter.php +++ b/src/Profile/Shopware/Converter/OrderConverter.php @@ -17,18 +17,22 @@ use Shopware\Core\Checkout\Cart\Tax\Struct\TaxRule; use Shopware\Core\Checkout\Cart\Tax\Struct\TaxRuleCollection; use Shopware\Core\Checkout\Cart\Tax\TaxCalculator; +use Shopware\Core\Checkout\Order\Aggregate\OrderAddress\OrderAddressDefinition; +use Shopware\Core\Checkout\Order\Aggregate\OrderDelivery\OrderDeliveryDefinition; +use Shopware\Core\Checkout\Order\Aggregate\OrderLineItem\OrderLineItemDefinition; +use Shopware\Core\Checkout\Order\Aggregate\OrderTransaction\OrderTransactionDefinition; use Shopware\Core\Defaults; use Shopware\Core\Framework\Context; use Shopware\Core\Framework\DataAbstractionLayer\EntityRepository; use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria; use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsFilter; use Shopware\Core\Framework\Log\Package; +use Shopware\Core\Framework\Util\Hasher; use Shopware\Core\System\SalesChannel\SalesChannelCollection; -use SwagMigrationAssistant\Exception\AssociationEntityRequiredMissingException; use SwagMigrationAssistant\Exception\MigrationException; use SwagMigrationAssistant\Migration\Converter\ConvertStruct; use SwagMigrationAssistant\Migration\DataSelection\DefaultEntities; -use SwagMigrationAssistant\Migration\Logging\Log\EmptyNecessaryFieldRunLog; +use SwagMigrationAssistant\Migration\Logging\Log\Builder\MigrationLogBuilder; use SwagMigrationAssistant\Migration\Logging\Log\UnknownEntityLog; use SwagMigrationAssistant\Migration\Logging\LoggingServiceInterface; use SwagMigrationAssistant\Migration\Mapping\Lookup\CountryLookup; @@ -64,29 +68,6 @@ abstract class OrderConverter extends ShopwareConverter protected string $runId; - /** - * @var list - */ - protected array $requiredDataFieldKeys = [ - 'customer', - 'currency', - 'currencyFactor', - 'payment', - 'status', - ]; - - /** - * @var list - */ - protected array $requiredAddressDataFieldKeys = [ - 'firstname', - 'lastname', - 'zipcode', - 'city', - 'street', - 'salutation', - ]; - protected int $paymentStatusId; /** @@ -106,7 +87,7 @@ public function __construct( } /** - * @throws AssociationEntityRequiredMissingException + * @throws MigrationException */ public function convert( array $data, @@ -118,37 +99,14 @@ public function convert( $this->runId = $migrationContext->getRunUuid(); $this->migrationContext = $migrationContext; - $fields = $this->checkForEmptyRequiredDataFields($data, $this->requiredDataFieldKeys); - if (empty($data['billingaddress']['id'])) { - $fields[] = 'billingaddress'; - } - if (isset($data['payment']) && empty($data['payment']['name'])) { - $fields[] = 'paymentMethod'; - } - - if (!empty($fields)) { - $this->loggingService->addLogEntry(new EmptyNecessaryFieldRunLog( - $this->runId, - DefaultEntities::ORDER, - $this->oldId, - \implode(',', $fields) - )); - - return new ConvertStruct(null, $data); - } + $connection = $migrationContext->getConnection(); + $this->connectionId = $connection->getId(); + $this->connectionName = $connection->getName(); $this->mainLocale = $data['_locale']; unset($data['_locale']); $this->context = $context; - $connection = $migrationContext->getConnection(); - $this->connectionName = ''; - $this->connectionId = ''; - if ($connection !== null) { - $this->connectionId = $connection->getId(); - $this->connectionName = $connection->getName(); - } - $converted = []; $this->mainMapping = $this->mappingService->getOrCreateMapping( $this->connectionId, @@ -157,7 +115,7 @@ public function convert( $this->context, $this->checksum ); - $converted['id'] = (string) $this->mainMapping['entityUuid']; + $converted['id'] = (string) $this->mainMapping['entityId']; unset($data['id']); $this->uuid = $converted['id']; @@ -190,24 +148,28 @@ public function convert( ); $converted['orderCustomer'] = [ - 'id' => $orderCustomerMapping['entityUuid'], - 'customerId' => $customerMapping['entityUuid'], + 'id' => $orderCustomerMapping['entityId'], + 'customerId' => $customerMapping['entityId'], ]; $this->mappingIds[] = $customerMapping['id']; $this->mappingIds[] = $orderCustomerMapping['id']; unset($customerMapping); - $salutationUuid = $this->getSalutation($data['customer']['salutation']); - if ($salutationUuid === null) { - return new ConvertStruct(null, $data); + $salutationUuid = null; + if (isset($data['customer']['salutation'])) { + $salutationUuid = $this->getSalutation($data['customer']['salutation']); + } + if ($salutationUuid !== null) { + $converted['orderCustomer']['salutationId'] = $salutationUuid; } - $converted['orderCustomer']['salutationId'] = $salutationUuid; - $this->convertValue($converted['orderCustomer'], 'email', $data['customer'], 'email'); - $this->convertValue($converted['orderCustomer'], 'firstName', $data['customer'], 'firstname'); - $this->convertValue($converted['orderCustomer'], 'lastName', $data['customer'], 'lastname'); - $this->convertValue($converted['orderCustomer'], 'customerNumber', $data['customer'], 'customernumber'); - unset($data['userID'], $data['customer']); + if (isset($data['customer'])) { + $this->convertValue($converted['orderCustomer'], 'email', $data['customer'], 'email'); + $this->convertValue($converted['orderCustomer'], 'firstName', $data['customer'], 'firstname'); + $this->convertValue($converted['orderCustomer'], 'lastName', $data['customer'], 'lastname'); + $this->convertValue($converted['orderCustomer'], 'customerNumber', $data['customer'], 'customernumber'); + unset($data['userID'], $data['customer']); + } $this->convertValue($converted, 'currencyFactor', $data, 'currencyFactor', self::TYPE_FLOAT); @@ -215,19 +177,10 @@ public function convert( if (isset($data['currency'])) { $currencyUuid = $this->currencyLookup->get($data['currency'], $context); } - if ($currencyUuid === null) { - $this->loggingService->addLogEntry(new EmptyNecessaryFieldRunLog( - $this->runId, - DefaultEntities::ORDER, - $this->oldId, - 'currency' - )); - - return new ConvertStruct(null, $data); + if ($currencyUuid !== null) { + $converted['currencyId'] = $currencyUuid; } - $converted['currencyId'] = $currencyUuid; - $converted['itemRounding'] = [ 'decimals' => $context->getRounding()->getDecimals(), 'interval' => 0.01, @@ -237,26 +190,20 @@ public function convert( $this->convertValue($converted, 'orderDateTime', $data, 'ordertime', self::TYPE_DATETIME); - $stateMapping = $this->mappingService->getMapping( - $this->connectionId, - OrderStateReader::getMappingName(), - (string) $data['status'], - $this->context - ); - - if ($stateMapping === null) { - $this->loggingService->addLogEntry(new UnknownEntityLog( - $this->runId, - 'order_state', + $stateMapping = null; + if (isset($data['status'])) { + $stateMapping = $this->mappingService->getMapping( + $this->connectionId, + OrderStateReader::getMappingName(), (string) $data['status'], - DefaultEntities::ORDER, - $this->oldId - )); + $this->context + ); + } - return new ConvertStruct(null, $data); + if ($stateMapping !== null) { + $converted['stateId'] = $stateMapping['entityId']; + $this->mappingIds[] = $stateMapping['id']; } - $converted['stateId'] = $stateMapping['entityUuid']; - $this->mappingIds[] = $stateMapping['id']; $shippingGross = (float) $data['invoice_shipping']; $shippingNet = (float) $data['invoice_shipping_net']; @@ -281,7 +228,7 @@ public function convert( $taxStatus = $this->getTaxStatus($data); $taxRules = $this->getTaxRules($data, $taxStatus); - $converted['lineItems'] = $this->getLineItems($data['details'], $taxRules, $taxStatus); + $converted['lineItems'] = $this->getLineItems($data['details'], $taxStatus); $converted['price'] = new CartPrice( (float) $data['invoice_amount_net'], @@ -321,22 +268,18 @@ public function convert( $this->applyTransactions($data, $converted); unset($data['cleared'], $data['paymentstatus']); - $billingAddress = $this->getAddress($data['billingaddress']); - if (empty($billingAddress)) { - $this->loggingService->addLogEntry(new EmptyNecessaryFieldRunLog( - $this->runId, - DefaultEntities::ORDER, - $this->oldId, - 'billingaddress' - )); + $billingAddress = null; + if (isset($data['billingaddress']) && \is_array($data['billingaddress'])) { + $billingAddress = $this->getAddress($data['billingaddress']); + } - return new ConvertStruct(null, $data); + if (!empty($billingAddress)) { + $converted['billingAddressId'] = $billingAddress['id']; + $converted['addresses'][] = $billingAddress; } if (isset($data['billingaddress']['ustid']) && $data['billingaddress']['ustid'] !== '') { $converted['orderCustomer']['vatIds'][] = $data['billingaddress']['ustid']; } - $converted['billingAddressId'] = $billingAddress['id']; - $converted['addresses'][] = $billingAddress; unset($data['billingaddress']); if (isset($data['subshopID'])) { @@ -348,7 +291,7 @@ public function convert( ); if ($mapping !== null) { - $converted['salesChannelId'] = $mapping['entityUuid']; + $converted['salesChannelId'] = $mapping['entityId']; $this->mappingIds[] = $mapping['id']; unset($data['subshopID']); } @@ -374,7 +317,7 @@ public function convert( } unset($data['locale']); - $converted['deepLinkCode'] = \md5($converted['id']); + $converted['deepLinkCode'] = Hasher::hash($converted['id']); // Legacy data which don't need a mapping or there is no equivalent field unset( @@ -429,17 +372,19 @@ protected function applyTransactions(array $data, array &$converted): void ); if ($mapping === null) { - $this->loggingService->addLogEntry(new UnknownEntityLog( - $this->runId, - 'transaction_state', - $data['cleared'], - DefaultEntities::ORDER_TRANSACTION, - $this->oldId - )); + $this->loggingService->addLogEntry( + MigrationLogBuilder::fromMigrationContext($this->migrationContext) + ->withEntityName(OrderTransactionDefinition::ENTITY_NAME) + ->withFieldName('stateId') + ->withFieldSourcePath('cleared') + ->withSourceData($data) + ->withConvertedData($converted) + ->build(UnknownEntityLog::class) + ); return; } - $stateId = $mapping['entityUuid']; + $stateId = $mapping['entityId']; $this->mappingIds[] = $mapping['id']; $mapping = $this->mappingService->getOrCreateMapping( @@ -454,7 +399,7 @@ protected function applyTransactions(array $data, array &$converted): void if ($paymentMethodUuid === null) { return; } - $id = $mapping['entityUuid']; + $id = $mapping['entityId']; $this->mappingIds[] = $mapping['id']; $transactions = [ @@ -479,28 +424,32 @@ protected function applyTransactions(array $data, array &$converted): void */ protected function getPaymentMethod(array $originalData): ?string { - $paymentMethodMapping = $this->mappingService->getMapping( - $this->connectionId, - PaymentMethodReader::getMappingName(), - $originalData['payment']['id'], - $this->context - ); + $paymentMethodMapping = null; + if (isset($originalData['payment']['id'])) { + $paymentMethodMapping = $this->mappingService->getMapping( + $this->connectionId, + PaymentMethodReader::getMappingName(), + $originalData['payment']['id'], + $this->context + ); + } if ($paymentMethodMapping === null) { - $this->loggingService->addLogEntry(new UnknownEntityLog( - $this->runId, - 'payment_method', - $originalData['payment']['id'], - DefaultEntities::ORDER_TRANSACTION, - $this->oldId - )); + $this->loggingService->addLogEntry( + MigrationLogBuilder::fromMigrationContext($this->migrationContext) + ->withEntityName(OrderTransactionDefinition::ENTITY_NAME) + ->withFieldName('paymentMethodId') + ->withFieldSourcePath('payment.id') + ->withSourceData($originalData) + ->build(UnknownEntityLog::class) + ); return null; } $this->mappingIds[] = $paymentMethodMapping['id']; - return $paymentMethodMapping['entityUuid']; + return $paymentMethodMapping['entityId']; } /** @@ -510,18 +459,6 @@ protected function getPaymentMethod(array $originalData): ?string */ protected function getAddress(array $originalData, string $type = self::BILLING_ADDRESS): array { - $fields = $this->checkForEmptyRequiredDataFields($originalData, $this->requiredAddressDataFieldKeys); - if (!empty($fields)) { - $this->loggingService->addLogEntry(new EmptyNecessaryFieldRunLog( - $this->runId, - DefaultEntities::ORDER_ADDRESS, - $originalData['id'], - \implode(',', $fields) - )); - - return []; - } - $entityName = DefaultEntities::ORDER_ADDRESS; if ($type !== self::BILLING_ADDRESS) { $entityName = DefaultEntities::ORDER_ADDRESS . '_' . $type; @@ -534,7 +471,7 @@ protected function getAddress(array $originalData, string $type = self::BILLING_ $originalData['id'], $this->context ); - $address['id'] = $mapping['entityUuid']; + $address['id'] = $mapping['entityId']; $this->mappingIds[] = $mapping['id']; $address['country'] = $this->getCountry($originalData['country']); @@ -587,7 +524,7 @@ protected function getCountry(array $oldCountryData): array $oldCountryData['id'], $this->context ); - $country['id'] = $mapping['entityUuid']; + $country['id'] = $mapping['entityId']; $this->mappingIds[] = $mapping['id']; } @@ -633,7 +570,7 @@ protected function applyCountryTranslation(array &$country, array $data): void $data['id'] . ':' . $this->mainLocale, $this->context ); - $localeTranslation['id'] = $mapping['entityUuid']; + $localeTranslation['id'] = $mapping['entityId']; $this->mappingIds[] = $mapping['id']; $languageUuid = $this->languageLookup->get($this->mainLocale, $this->context); @@ -658,13 +595,12 @@ protected function getCountryState(array $oldAddressData, string $newCountryId): if (!isset($oldAddressData['stateID'], $oldAddressData['country']['countryiso'], $oldAddressData['state']['shortcode'])) { $this->loggingService->addLogEntry( - new UnknownEntityLog( - $this->runId, - DefaultEntities::COUNTRY_STATE, - $oldAddressData['stateID'] ?? 'unknown', - DefaultEntities::ORDER, - $this->oldId - ) + MigrationLogBuilder::fromMigrationContext($this->migrationContext) + ->withEntityName(OrderAddressDefinition::ENTITY_NAME) + ->withFieldName('countryStateId') + ->withFieldSourcePath('stateID') + ->withSourceData($oldAddressData) + ->build(UnknownEntityLog::class) ); return []; @@ -696,19 +632,18 @@ protected function getCountryState(array $oldAddressData, string $newCountryId): $oldAddressData['state']['active'] )) { $this->loggingService->addLogEntry( - new UnknownEntityLog( - $this->runId, - DefaultEntities::COUNTRY_STATE, - $oldAddressData['stateID'], - DefaultEntities::ORDER, - $this->oldId - ) + MigrationLogBuilder::fromMigrationContext($this->migrationContext) + ->withEntityName(OrderAddressDefinition::ENTITY_NAME) + ->withFieldName('countryStateId') + ->withFieldSourcePath('name') + ->withSourceData($oldAddressData['state']) + ->build(UnknownEntityLog::class) ); return []; } - $state['id'] = $mapping['entityUuid']; + $state['id'] = $mapping['entityId']; $this->mappingIds[] = $mapping['id']; $oldStateData = $oldAddressData['state']; @@ -749,7 +684,7 @@ protected function applyCountryStateTranslation(array &$state, array $data): voi $data['id'] . ':' . $this->mainLocale, $this->context ); - $localeTranslation['id'] = $mapping['entityUuid']; + $localeTranslation['id'] = $mapping['entityId']; $this->mappingIds[] = $mapping['id']; $languageUuid = $this->languageLookup->get($this->mainLocale, $this->context); @@ -768,21 +703,26 @@ protected function applyCountryStateTranslation(array &$state, array $data): voi protected function getDeliveries(array $data, array $converted, CalculatedPrice $shippingCosts): array { $deliveries = []; - $deliveryStateMapping = $this->mappingService->getMapping( - $this->connectionId, - OrderDeliveryStateReader::getMappingName(), - (string) $data['status'], - $this->context - ); + $deliveryStateMapping = null; + if (isset($data['status'])) { + $deliveryStateMapping = $this->mappingService->getMapping( + $this->connectionId, + OrderDeliveryStateReader::getMappingName(), + (string) $data['status'], + $this->context + ); + } if ($deliveryStateMapping === null) { - $this->loggingService->addLogEntry(new UnknownEntityLog( - $this->runId, - 'order_delivery_state', - (string) $data['status'], - DefaultEntities::ORDER, - $this->oldId - )); + $this->loggingService->addLogEntry( + MigrationLogBuilder::fromMigrationContext($this->migrationContext) + ->withEntityName(OrderDeliveryDefinition::ENTITY_NAME) + ->withFieldName('stateId') + ->withFieldSourcePath('status') + ->withSourceData($data) + ->withConvertedData($converted) + ->build(UnknownEntityLog::class) + ); return []; } @@ -797,8 +737,8 @@ protected function getDeliveries(array $data, array $converted, CalculatedPrice $this->mappingIds[] = $mapping['id']; $delivery = [ - 'id' => $mapping['entityUuid'], - 'stateId' => $deliveryStateMapping['entityUuid'], + 'id' => $mapping['entityId'], + 'stateId' => $deliveryStateMapping['entityId'], 'shippingDateEarliest' => $converted['orderDateTime'], 'shippingDateLatest' => $converted['orderDateTime'], ]; @@ -834,7 +774,7 @@ protected function getDeliveries(array $data, array $converted, CalculatedPrice ); $this->mappingIds[] = $mapping['id']; $positions[] = [ - 'id' => $mapping['entityUuid'], + 'id' => $mapping['entityId'], 'orderLineItemId' => $lineItem['id'], 'price' => $lineItem['price'], ]; @@ -859,19 +799,20 @@ protected function getShippingMethod(string $shippingMethodId): ?string ); if ($shippingMethodMapping === null) { - $this->loggingService->addLogEntry(new UnknownEntityLog( - $this->runId, - DefaultEntities::SHIPPING_METHOD, - $shippingMethodId, - DefaultEntities::ORDER, - $this->oldId - )); + $this->loggingService->addLogEntry( + MigrationLogBuilder::fromMigrationContext($this->migrationContext) + ->withEntityName(OrderDeliveryDefinition::ENTITY_NAME) + ->withFieldName('shippingMethodId') + ->withFieldSourcePath('dispatchID') + ->withSourceData(['dispatchID' => $shippingMethodId]) + ->build(UnknownEntityLog::class) + ); return null; } $this->mappingIds[] = $shippingMethodMapping['id']; - return $shippingMethodMapping['entityUuid']; + return $shippingMethodMapping['entityId']; } /** @@ -879,7 +820,7 @@ protected function getShippingMethod(string $shippingMethodId): ?string * * @return array> */ - protected function getLineItems(array $originalData, TaxRuleCollection $taxRules, string $taxStatus): array + protected function getLineItems(array $originalData, string $taxStatus): array { $lineItems = []; @@ -895,8 +836,8 @@ protected function getLineItems(array $originalData, TaxRuleCollection $taxRules $this->mappingIds[] = $mapping['id']; $lineItem = [ - 'id' => $mapping['entityUuid'], - 'identifier' => $mapping['entityUuid'], + 'id' => $mapping['entityId'], + 'identifier' => $mapping['entityId'], ]; if ($isProduct) { @@ -909,8 +850,8 @@ protected function getLineItems(array $originalData, TaxRuleCollection $taxRules ); if ($mapping !== null) { - $lineItem['referencedId'] = $mapping['entityUuid']; - $lineItem['productId'] = $mapping['entityUuid']; + $lineItem['referencedId'] = $mapping['entityId']; + $lineItem['productId'] = $mapping['entityId']; $lineItem['payload']['productNumber'] = $originalLineItem['articleordernumber'] ?? ''; $this->mappingIds[] = $mapping['id']; } @@ -929,14 +870,16 @@ protected function getLineItems(array $originalData, TaxRuleCollection $taxRules $this->convertValue($lineItem, 'quantity', $originalLineItem, 'quantity', self::TYPE_INTEGER); $this->convertValue($lineItem, 'label', $originalLineItem, 'name'); + $lineItemTaxRules = new TaxRuleCollection([new TaxRule((float) $originalLineItem['tax_rate'])]); + $calculatedTax = null; $totalPrice = $lineItem['quantity'] * $originalLineItem['price']; if ($taxStatus === CartPrice::TAX_STATE_NET) { - $calculatedTax = $this->taxCalculator->calculateNetTaxes($totalPrice, $taxRules); + $calculatedTax = $this->taxCalculator->calculateNetTaxes($totalPrice, $lineItemTaxRules); } if ($taxStatus === CartPrice::TAX_STATE_GROSS) { - $calculatedTax = $this->taxCalculator->calculateGrossTaxes($totalPrice, $taxRules); + $calculatedTax = $this->taxCalculator->calculateGrossTaxes($totalPrice, $lineItemTaxRules); } if ($taxStatus === CartPrice::TAX_STATE_FREE) { @@ -950,13 +893,13 @@ protected function getLineItems(array $originalData, TaxRuleCollection $taxRules (float) $originalLineItem['price'], (float) $totalPrice, $calculatedTax, - $taxRules, + $lineItemTaxRules, (int) $lineItem['quantity'] ); $lineItem['priceDefinition'] = new QuantityPriceDefinition( (float) $originalLineItem['price'], - $taxRules, + $lineItemTaxRules, $lineItem['quantity'] ?? 1 ); @@ -1026,20 +969,21 @@ protected function getSalutation(string $salutation): ?string ); if ($salutationMapping === null) { - $this->loggingService->addLogEntry(new UnknownEntityLog( - $this->runId, - 'salutation', - $salutation, - DefaultEntities::ORDER, - $this->oldId - )); + $this->loggingService->addLogEntry( + MigrationLogBuilder::fromMigrationContext($this->migrationContext) + ->withEntityName(OrderAddressDefinition::ENTITY_NAME) + ->withFieldName('salutationId') + ->withFieldSourcePath('salutation') + ->withSourceData(['salutation' => $salutation]) + ->build(UnknownEntityLog::class) + ); return null; } $this->mappingIds[] = $salutationMapping['id']; - return $salutationMapping['entityUuid']; + return $salutationMapping['entityId']; } /** @@ -1057,13 +1001,14 @@ private function getOrderLineItemDownload(array $originalEsdItem): ?array ); if (!\is_array($mediaMapping)) { - $this->loggingService->addLogEntry(new UnknownEntityLog( - $this->runId, - 'product_download_media', - $originalEsdItem['esdID'], - DefaultEntities::ORDER, - $this->oldId - )); + $this->loggingService->addLogEntry( + MigrationLogBuilder::fromMigrationContext($this->migrationContext) + ->withEntityName(OrderLineItemDefinition::ENTITY_NAME) + ->withFieldName('coverId') + ->withFieldSourcePath('esd.esdID') + ->withSourceData($originalEsdItem) + ->build(UnknownEntityLog::class) + ); return null; } @@ -1087,8 +1032,8 @@ private function getOrderLineItemDownload(array $originalEsdItem): ?array } return [ - 'id' => $mapping['entityUuid'], - 'mediaId' => $mediaMapping['entityUuid'], + 'id' => $mapping['entityId'], + 'mediaId' => $mediaMapping['entityId'], 'accessGranted' => $accessGranted, 'position' => 0, ]; diff --git a/src/Profile/Shopware/Converter/OrderDocumentConverter.php b/src/Profile/Shopware/Converter/OrderDocumentConverter.php index 0d098333d..f3590b14f 100644 --- a/src/Profile/Shopware/Converter/OrderDocumentConverter.php +++ b/src/Profile/Shopware/Converter/OrderDocumentConverter.php @@ -15,9 +15,8 @@ use Shopware\Core\Framework\Util\Random; use SwagMigrationAssistant\Migration\Converter\ConvertStruct; use SwagMigrationAssistant\Migration\DataSelection\DefaultEntities; -use SwagMigrationAssistant\Migration\Logging\Log\AssociationRequiredMissingLog; -use SwagMigrationAssistant\Migration\Logging\Log\DocumentTypeNotSupported; -use SwagMigrationAssistant\Migration\Logging\Log\EmptyNecessaryFieldRunLog; +use SwagMigrationAssistant\Migration\Logging\Log\Builder\MigrationLogBuilder; +use SwagMigrationAssistant\Migration\Logging\Log\DocumentTypeNotSupportedLog; use SwagMigrationAssistant\Migration\Logging\LoggingServiceInterface; use SwagMigrationAssistant\Migration\Mapping\Lookup\DocumentTypeLookup; use SwagMigrationAssistant\Migration\Mapping\Lookup\MediaDefaultFolderLookup; @@ -72,42 +71,11 @@ public function convert(array $data, Context $context, MigrationContextInterface $this->context = $context; $connection = $migrationContext->getConnection(); - $this->connectionName = ''; - $this->connectionId = ''; - if ($connection !== null) { - $this->connectionId = $connection->getId(); - $this->connectionName = $connection->getName(); - } + $this->connectionId = $connection->getId(); + $this->connectionName = $connection->getName(); - $oldData = $data; $converted = []; - if (empty($data['hash'])) { - $this->loggingService->addLogEntry( - new EmptyNecessaryFieldRunLog( - $this->migrationContext->getRunUuid(), - DefaultEntities::ORDER_DOCUMENT, - $this->oldId, - 'hash' - ) - ); - - return new ConvertStruct(null, $oldData); - } - - if (!isset($data['documenttype'])) { - $this->loggingService->addLogEntry( - new EmptyNecessaryFieldRunLog( - $this->migrationContext->getRunUuid(), - DefaultEntities::ORDER_DOCUMENT, - $this->oldId, - 'documenttype' - ) - ); - - return new ConvertStruct(null, $oldData); - } - $orderMapping = $this->mappingService->getMapping( $this->connectionId, DefaultEntities::ORDER, @@ -115,21 +83,11 @@ public function convert(array $data, Context $context, MigrationContextInterface $context ); - if ($orderMapping === null) { - $this->loggingService->addLogEntry( - new AssociationRequiredMissingLog( - $this->migrationContext->getRunUuid(), - DefaultEntities::ORDER, - $this->oldId, - DefaultEntities::ORDER_DOCUMENT - ) - ); - - return new ConvertStruct(null, $oldData); + if ($orderMapping !== null) { + $this->mappingIds[] = $orderMapping['id']; + $converted['orderId'] = $orderMapping['entityId']; } unset($data['orderID']); - $orderUuid = $orderMapping['entityUuid']; - $this->mappingIds[] = $orderMapping['id']; $this->mainMapping = $this->mappingService->getOrCreateMapping( $this->connectionId, @@ -138,27 +96,27 @@ public function convert(array $data, Context $context, MigrationContextInterface $context, $this->checksum ); - $converted['id'] = $this->mainMapping['entityUuid']; - $converted['orderId'] = $orderUuid; + + $converted['id'] = $this->mainMapping['entityId']; $converted['fileType'] = FileTypes::PDF; $converted['static'] = true; $converted['deepLinkCode'] = Random::getAlphanumericString(32); $converted['config'] = []; + if (isset($data['docID'])) { $converted['config']['documentNumber'] = $data['docID']; + if (isset($data['documenttype'])) { + $converted['documentType'] = $this->getDocumentType($data['documenttype']); + } + if (isset($data['documenttype']['key']) && $data['documenttype']['key'] === 'invoice') { $converted['config']['custom']['invoiceNumber'] = $data['docID']; } - unset($data['docID']); + unset($data['docID'], $data['documenttype']); } - $documentType = $this->getDocumentType($data['documenttype']); - - $converted['documentType'] = $documentType; - unset($data['documenttype']); - if (isset($data['attributes'])) { $converted['customFields'] = $this->getAttributes($data['attributes'], DefaultEntities::ORDER_DOCUMENT, $this->connectionName, ['id', 'documentID'], $this->context); } @@ -202,11 +160,15 @@ protected function getDocumentType(array $data): array return $documentType; } - $this->loggingService->addLogEntry(new DocumentTypeNotSupported( - $this->runId, - $data['id'], - $mappedKey - )); + $this->loggingService->addLogEntry( + MigrationLogBuilder::fromMigrationContext($this->migrationContext) + ->withEntityName(DocumentDefinition::ENTITY_NAME) + ->withFieldName('documentType') + ->withFieldSourcePath('key') + ->withSourceData($data) + ->withConvertedData($documentType) + ->build(DocumentTypeNotSupportedLog::class) + ); $mapping = $this->mappingService->getOrCreateMapping( $this->connectionId, @@ -216,7 +178,7 @@ protected function getDocumentType(array $data): array ); $this->mappingIds[] = $mapping['id']; - $documentType['id'] = $mapping['entityUuid']; + $documentType['id'] = $mapping['entityId']; $documentType['name'] = $data['name']; $documentType['technicalName'] = $mappedKey; @@ -238,19 +200,21 @@ protected function getMediaFile(array $data): array ); $newMedia = []; - $newMedia['id'] = $mapping['entityUuid']; + $newMedia['id'] = $mapping['entityId']; $this->mappingIds[] = $mapping['id']; - $this->mediaFileService->saveMediaFile( - [ - 'runId' => $this->runId, - 'entity' => OrderDocumentDataSet::getEntity(), - 'uri' => $data['hash'], - 'fileName' => $data['hash'], - 'fileSize' => 0, - 'mediaId' => $newMedia['id'], - ] - ); + if (!empty($data['hash'])) { + $this->mediaFileService->saveMediaFile( + [ + 'runId' => $this->runId, + 'entity' => OrderDocumentDataSet::getEntity(), + 'uri' => $data['hash'], + 'fileName' => $data['hash'], + 'fileSize' => 0, + 'mediaId' => $newMedia['id'], + ] + ); + } $newMedia['private'] = true; $this->convertValue($newMedia, 'title', $data, 'hash'); diff --git a/src/Profile/Shopware/Converter/ProductConverter.php b/src/Profile/Shopware/Converter/ProductConverter.php index 1a4d04fc3..9499ec730 100644 --- a/src/Profile/Shopware/Converter/ProductConverter.php +++ b/src/Profile/Shopware/Converter/ProductConverter.php @@ -7,18 +7,24 @@ namespace SwagMigrationAssistant\Profile\Shopware\Converter; +use Shopware\Core\Content\Media\MediaDefinition; use Shopware\Core\Content\Product\Aggregate\ProductDownload\ProductDownloadDefinition; +use Shopware\Core\Content\Product\Aggregate\ProductMedia\ProductMediaDefinition; +use Shopware\Core\Content\Product\Aggregate\ProductPrice\ProductPriceDefinition; use Shopware\Core\Content\Product\Aggregate\ProductVisibility\ProductVisibilityDefinition; +use Shopware\Core\Content\Product\ProductDefinition; use Shopware\Core\Defaults; use Shopware\Core\Framework\Context; use Shopware\Core\Framework\Log\Package; use Shopware\Core\Framework\Rule\Container\AndRule; use Shopware\Core\Framework\Rule\Container\OrRule; +use Shopware\Core\Framework\Util\Hasher; use Shopware\Core\Framework\Uuid\Uuid; use SwagMigrationAssistant\Exception\MigrationException; use SwagMigrationAssistant\Migration\Converter\ConvertStruct; use SwagMigrationAssistant\Migration\DataSelection\DefaultEntities; -use SwagMigrationAssistant\Migration\Logging\Log\CannotConvertChildEntity; +use SwagMigrationAssistant\Migration\Logging\Log\Builder\MigrationLogBuilder; +use SwagMigrationAssistant\Migration\Logging\Log\CannotConvertChildEntityLog; use SwagMigrationAssistant\Migration\Logging\Log\EmptyNecessaryFieldRunLog; use SwagMigrationAssistant\Migration\Logging\LoggingServiceInterface; use SwagMigrationAssistant\Migration\Mapping\Lookup\DeliveryTimeLookup; @@ -45,14 +51,6 @@ abstract class ProductConverter extends ShopwareConverter protected string $runId; - /** - * @var list - */ - protected array $requiredDataFieldKeys = [ - 'tax', - 'prices', - ]; - /** * @var array{minPurchase: int, purchaseSteps: int, shippingFree: bool, restockTime: int} */ @@ -137,24 +135,8 @@ public function convert( $this->locale = $data['_locale']; $connection = $migrationContext->getConnection(); - $this->connectionName = ''; - $this->connectionId = ''; - if ($connection !== null) { - $this->connectionId = $connection->getId(); - $this->connectionName = $connection->getName(); - } - - $fields = $this->checkForEmptyRequiredDataFields($data, $this->requiredDataFieldKeys); - if (!empty($fields)) { - $this->loggingService->addLogEntry(new EmptyNecessaryFieldRunLog( - $this->runId, - DefaultEntities::PRODUCT, - $this->oldProductId, - \implode(',', $fields) - )); - - return new ConvertStruct(null, $data); - } + $this->connectionId = $connection->getId(); + $this->connectionName = $connection->getName(); $this->productType = (int) $data['detail']['kind']; unset($data['detail']['kind']); @@ -209,7 +191,7 @@ protected function convertMainProduct(array $data): ConvertStruct $data['id'], $this->context ); - $containerUuid = $containerMapping['entityUuid']; + $containerUuid = $containerMapping['entityId']; $converted = []; $converted['id'] = $containerUuid; @@ -229,7 +211,7 @@ protected function convertMainProduct(array $data): ConvertStruct $this->context, $this->checksum ); - $converted['children'][0]['id'] = $this->mainMapping['entityUuid']; + $converted['children'][0]['id'] = $this->mainMapping['entityId']; if (isset($converted['children'][0]['media'])) { if (isset($converted['children'][0]['cover'])) { @@ -242,9 +224,9 @@ protected function convertMainProduct(array $data): ConvertStruct $media['id'], $this->context ); - $productMediaRelationUuid = $productMediaRelationMapping['entityUuid']; + $productMediaRelationUuid = $productMediaRelationMapping['entityId']; $this->mappingIds[] = $productMediaRelationMapping['id']; - $media['productId'] = $this->mainMapping['entityUuid']; + $media['productId'] = $this->mainMapping['entityId']; $media['id'] = $productMediaRelationUuid; if (isset($coverMediaUuid) && $media['media']['id'] === $coverMediaUuid) { @@ -305,8 +287,8 @@ protected function convertVariantProduct(array $data): ConvertStruct ); $converted = []; - $converted['id'] = $this->mainMapping['entityUuid']; - $converted['parentId'] = $parentMapping['entityUuid']; + $converted['id'] = $this->mainMapping['entityId']; + $converted['parentId'] = $parentMapping['entityId']; $this->mappingIds[] = $parentMapping['id']; $converted = $this->getProductData($data, $converted); unset($data['detail']['id'], $data['detail']['articleID'], $data['categories']); @@ -342,7 +324,7 @@ private function getUuidForProduct(array &$data): array ); $converted = []; - $converted['id'] = $this->mainMapping['entityUuid']; + $converted['id'] = $this->mainMapping['entityId']; $mapping = $this->mappingService->getOrCreateMapping( $this->connectionId, @@ -387,12 +369,15 @@ private function getProductData(array &$data, array $converted): array $converted['price'] = $this->getPrice($data['prices'][0], $converted['tax']['taxRate']); if (empty($converted['price'])) { - $this->loggingService->addLogEntry(new EmptyNecessaryFieldRunLog( - $this->runId, - DefaultEntities::PRODUCT, - $this->oldProductId, - 'currency' - )); + $this->loggingService->addLogEntry( + MigrationLogBuilder::fromMigrationContext($this->migrationContext) + ->withEntityName(ProductDefinition::ENTITY_NAME) + ->withFieldName('price') + ->withFieldSourcePath('prices') + ->withSourceData($data) + ->withConvertedData($converted) + ->build(EmptyNecessaryFieldRunLog::class) + ); } $converted['prices'] = $this->getPrices($data['prices'], $converted); @@ -605,7 +590,7 @@ private function getDeliveryTime(string $shippingTime): ?array ); if ($mapping !== null) { - $convertedDeliveryTime['id'] = $mapping['entityUuid']; + $convertedDeliveryTime['id'] = $mapping['entityId']; return $convertedDeliveryTime; } @@ -666,21 +651,21 @@ private function applyOptions(array &$converted, array &$data): void $optionMapping = $this->mappingService->getOrCreateMapping( $this->connectionId, DefaultEntities::PROPERTY_GROUP_OPTION, - \hash('md5', \mb_strtolower($option['name'] . '_' . $option['group']['name'])), + Hasher::hash(\mb_strtolower($option['name'] . '_' . $option['group']['name']), 'md5'), $this->context ); $this->mappingIds[] = $optionMapping['id']; $optionGroupMapping = $this->mappingService->getOrCreateMapping( $this->connectionId, DefaultEntities::PROPERTY_GROUP, - \hash('md5', \mb_strtolower($option['group']['name'])), + Hasher::hash(\mb_strtolower($option['group']['name']), 'md5'), $this->context ); $this->mappingIds[] = $optionGroupMapping['id']; $optionElement = [ - 'id' => $optionMapping['entityUuid'], + 'id' => $optionMapping['entityId'], 'group' => [ - 'id' => $optionGroupMapping['entityUuid'], + 'id' => $optionGroupMapping['entityId'], ], ]; @@ -715,7 +700,7 @@ private function getManufacturer(array $data): array $this->context ); $manufacturer = []; - $manufacturer['id'] = $mapping['entityUuid']; + $manufacturer['id'] = $mapping['entityId']; $this->mappingIds[] = $mapping['id']; $this->applyManufacturerTranslation($manufacturer, $data); @@ -762,7 +747,7 @@ private function applyManufacturerTranslation(array &$manufacturer, array $data) $data['id'] . ':' . $this->locale, $this->context ); - $localeTranslation['id'] = $mapping['entityUuid']; + $localeTranslation['id'] = $mapping['entityId']; $this->mappingIds[] = $mapping['id']; $languageUuid = $this->languageLookup->get($this->locale, $this->context); @@ -788,7 +773,7 @@ private function getTax(array $taxData): array $taxData['id'], $this->context ); - $taxUuid = $mapping['entityUuid']; + $taxUuid = $mapping['entityId']; $this->mappingIds[] = $mapping['id']; } @@ -813,7 +798,7 @@ private function getUnit(array $data): array $data['id'], $this->context ); - $unit['id'] = $mapping['entityUuid']; + $unit['id'] = $mapping['entityId']; $this->mappingIds[] = $mapping['id']; $this->applyUnitTranslation($unit, $data); @@ -850,7 +835,7 @@ private function applyUnitTranslation(array &$unit, array $data): void $data['id'] . ':' . $this->locale, $this->context ); - $localeTranslation['id'] = $mapping['entityUuid']; + $localeTranslation['id'] = $mapping['entityId']; $this->mappingIds[] = $mapping['id']; $languageUuid = $this->languageLookup->get($this->locale, $this->context); @@ -877,7 +862,7 @@ private function getEsdFiles(array $esdFiles, string $oldVariantId, array $conve $oldVariantId . '_' . $esdFile['id'], $this->context ); - $newProductMedia['id'] = $mapping['entityUuid']; + $newProductMedia['id'] = $mapping['entityId']; $this->mappingIds[] = $mapping['id']; $newProductMedia['productId'] = $converted['id']; @@ -890,28 +875,36 @@ private function getEsdFiles(array $esdFiles, string $oldVariantId, array $conve $this->context ); - $newMedia['id'] = $mapping['entityUuid']; + $newMedia['id'] = $mapping['entityId']; $this->mappingIds[] = $mapping['id']; + if (empty($esdFile['name'])) { - $this->loggingService->addLogEntry(new CannotConvertChildEntity( - $this->runId, - DefaultEntities::PRODUCT_DOWNLOAD, - DefaultEntities::PRODUCT, - $this->oldProductId - )); + $this->loggingService->addLogEntry( + MigrationLogBuilder::fromMigrationContext($this->migrationContext) + ->withEntityName(MediaDefinition::ENTITY_NAME) + ->withFieldName('name') + ->withFieldSourcePath('name') + ->withSourceData($esdFile) + ->withConvertedData($newMedia) + ->build(CannotConvertChildEntityLog::class) + ); continue; } try { $path = \unserialize($esdFile['path'], ['allowed_classes' => false]); - } catch (\Throwable $error) { - $this->loggingService->addLogEntry(new CannotConvertChildEntity( - $this->runId, - DefaultEntities::PRODUCT_DOWNLOAD, - DefaultEntities::PRODUCT, - $this->oldProductId - )); + } catch (\Throwable $e) { + $this->loggingService->addLogEntry( + MigrationLogBuilder::fromMigrationContext($this->migrationContext) + ->withEntityName(MediaDefinition::ENTITY_NAME) + ->withFieldName('path') + ->withFieldSourcePath('path') + ->withSourceData($esdFile) + ->withExceptionMessage($e->getMessage()) + ->withExceptionTrace($e->getTrace()) + ->build(CannotConvertChildEntityLog::class) + ); continue; } @@ -927,17 +920,29 @@ private function getEsdFiles(array $esdFiles, string $oldVariantId, array $conve ] ); - $esdFile['name'] = \pathinfo($esdFile['name'], \PATHINFO_FILENAME); - $this->convertValue($newMedia, 'title', $esdFile, 'name'); + $fileName = \pathinfo($esdFile['name'], \PATHINFO_FILENAME); + $sourceData = ['name' => $fileName]; + + $this->convertValue( + $newMedia, + 'title', + $sourceData, + 'name' + ); $albumId = $this->mediaFolderLookup->get(ProductDownloadDefinition::ENTITY_NAME, $this->context); if ($albumId === null) { - $this->loggingService->addLogEntry(new CannotConvertChildEntity( - $this->runId, - DefaultEntities::PRODUCT_DOWNLOAD, - DefaultEntities::PRODUCT, - $this->oldProductId - )); + $this->loggingService->addLogEntry( + MigrationLogBuilder::fromMigrationContext($this->migrationContext) + ->withEntityName(MediaDefinition::ENTITY_NAME) + ->withFieldName('mediaFolderId') + ->withSourceData([ + 'file_name' => $fileName, + 'source_data' => $sourceData, + 'media_folder' => ProductDownloadDefinition::ENTITY_NAME, + ]) + ->build(CannotConvertChildEntityLog::class) + ); continue; } @@ -966,12 +971,14 @@ private function getMedia(array $media, string $oldVariantId, array $converted): $mediaObjects = []; foreach ($media as $mediaData) { if (!isset($mediaData['media']['id'])) { - $this->loggingService->addLogEntry(new CannotConvertChildEntity( - $this->runId, - DefaultEntities::PRODUCT_MEDIA, - DefaultEntities::PRODUCT, - $this->oldProductId - )); + $this->loggingService->addLogEntry( + MigrationLogBuilder::fromMigrationContext($this->migrationContext) + ->withEntityName(ProductMediaDefinition::ENTITY_NAME) + ->withFieldName('mediaId') + ->withFieldSourcePath('media.id') + ->withSourceData($mediaData) + ->build(CannotConvertChildEntityLog::class) + ); continue; } @@ -983,7 +990,7 @@ private function getMedia(array $media, string $oldVariantId, array $converted): $oldVariantId . $mediaData['id'], $this->context ); - $newProductMedia['id'] = $mapping['entityUuid']; + $newProductMedia['id'] = $mapping['entityId']; $this->mappingIds[] = $mapping['id']; $newProductMedia['productId'] = $converted['id']; $this->convertValue($newProductMedia, 'position', $mediaData, 'position', self::TYPE_INTEGER); @@ -995,7 +1002,7 @@ private function getMedia(array $media, string $oldVariantId, array $converted): $mediaData['media']['id'], $this->context ); - $newMedia['id'] = $mapping['entityUuid']; + $newMedia['id'] = $mapping['entityId']; $this->mappingIds[] = $mapping['id']; if (empty($mediaData['media']['name'])) { @@ -1025,7 +1032,7 @@ private function getMedia(array $media, string $oldVariantId, array $converted): ); if ($albumMapping !== null) { - $newMedia['mediaFolderId'] = $albumMapping['entityUuid']; + $newMedia['mediaFolderId'] = $albumMapping['entityId']; $this->mappingIds[] = $albumMapping['id']; } @@ -1127,7 +1134,7 @@ private function applyMediaTranslation(array &$media, array $data): void $data['media']['id'] . ':' . $this->locale, $this->context ); - $localeTranslation['id'] = $mapping['entityUuid']; + $localeTranslation['id'] = $mapping['entityId']; $this->mappingIds[] = $mapping['id']; $languageUuid = $this->languageLookup->get($this->locale, $this->context); @@ -1151,7 +1158,7 @@ private function getManufacturerMedia(array $media): array $this->context ); $manufacturerMedia = []; - $manufacturerMedia['id'] = $mapping['entityUuid']; + $manufacturerMedia['id'] = $mapping['entityId']; $this->mappingIds[] = $mapping['id']; if (empty($media['name'])) { @@ -1168,7 +1175,7 @@ private function getManufacturerMedia(array $media): array ); if ($albumMapping !== null) { - $manufacturerMedia['mediaFolderId'] = $albumMapping['entityUuid']; + $manufacturerMedia['mediaFolderId'] = $albumMapping['entityId']; $this->mappingIds[] = $albumMapping['id']; } @@ -1200,10 +1207,10 @@ private function applyOptionTranslation(array &$option, array $data): void $mapping = $this->mappingService->getOrCreateMapping( $this->connectionId, DefaultEntities::PROPERTY_GROUP_OPTION_TRANSLATION, - \hash('md5', \mb_strtolower($data['name'] . '_' . $data['group']['name'])) . ':' . $this->locale, + Hasher::hash(\mb_strtolower($data['name'] . '_' . $data['group']['name']), 'md5') . ':' . $this->locale, $this->context ); - $localeOptionTranslation['id'] = $mapping['entityUuid']; + $localeOptionTranslation['id'] = $mapping['entityId']; $this->mappingIds[] = $mapping['id']; $this->convertValue($localeOptionTranslation, 'name', $data, 'name'); @@ -1212,10 +1219,10 @@ private function applyOptionTranslation(array &$option, array $data): void $mapping = $this->mappingService->getOrCreateMapping( $this->connectionId, DefaultEntities::PROPERTY_GROUP_TRANSLATION, - \hash('md5', \mb_strtolower($data['group']['name'])) . ':' . $this->locale, + Hasher::hash(\mb_strtolower($data['group']['name']), 'md5') . ':' . $this->locale, $this->context ); - $localeGroupTranslation['id'] = $mapping['entityUuid']; + $localeGroupTranslation['id'] = $mapping['entityId']; $this->mappingIds[] = $mapping['id']; $this->convertValue($localeGroupTranslation, 'name', $data['group'], 'name'); @@ -1247,7 +1254,7 @@ private function getPrice(array $priceData, float $taxRate): array if (!isset($currencyMapping)) { return []; } - $this->currencyUuid = $currencyMapping['entityUuid']; + $this->currencyUuid = $currencyMapping['entityId']; $this->mappingIds[] = $currencyMapping['id']; $price = []; @@ -1305,7 +1312,7 @@ private function getPrices(array $priceData, array $converted): array if ($customerGroupMapping === null) { continue; } - $customerGroupUuid = $customerGroupMapping['entityUuid']; + $customerGroupUuid = $customerGroupMapping['entityId']; $this->mappingIds[] = $customerGroupMapping['id']; $mapping = $this->mappingService->getOrCreateMapping( @@ -1314,7 +1321,7 @@ private function getPrices(array $priceData, array $converted): array 'customerGroupRule_productPriceRule_' . $price['id'] . '_' . $price['customergroup']['id'], $this->context ); - $productPriceRuleUuid = $mapping['entityUuid']; + $productPriceRuleUuid = $mapping['entityId']; $this->mappingIds[] = $mapping['id']; $mapping = $this->mappingService->getOrCreateMapping( @@ -1323,7 +1330,7 @@ private function getPrices(array $priceData, array $converted): array 'customerGroupRule_' . $price['customergroup']['id'], $this->context ); - $priceRuleUuid = $mapping['entityUuid']; + $priceRuleUuid = $mapping['entityId']; $this->mappingIds[] = $mapping['id']; $mapping = $this->mappingService->getOrCreateMapping( @@ -1332,7 +1339,7 @@ private function getPrices(array $priceData, array $converted): array 'customerGroupRule_orContainer_' . $price['customergroup']['id'], $this->context ); - $orContainerUuid = $mapping['entityUuid']; + $orContainerUuid = $mapping['entityId']; $this->mappingIds[] = $mapping['id']; $mapping = $this->mappingService->getOrCreateMapping( @@ -1341,7 +1348,7 @@ private function getPrices(array $priceData, array $converted): array 'customerGroupRule_andContainer_' . $price['customergroup']['id'], $this->context ); - $andContainerUuid = $mapping['entityUuid']; + $andContainerUuid = $mapping['entityId']; $this->mappingIds[] = $mapping['id']; $mapping = $this->mappingService->getOrCreateMapping( @@ -1350,18 +1357,21 @@ private function getPrices(array $priceData, array $converted): array 'customerGroupRule_condition_' . $price['customergroup']['id'], $this->context ); - $conditionUuid = $mapping['entityUuid']; + $conditionUuid = $mapping['entityId']; $this->mappingIds[] = $mapping['id']; $priceArray = $this->getPrice($price, $converted['tax']['taxRate']); if (empty($priceArray)) { - $this->loggingService->addLogEntry(new EmptyNecessaryFieldRunLog( - $this->runId, - DefaultEntities::PRODUCT_PRICE, - $this->oldProductId, - 'currencyId' - )); + $this->loggingService->addLogEntry( + MigrationLogBuilder::fromMigrationContext($this->migrationContext) + ->withEntityName(ProductPriceDefinition::ENTITY_NAME) + ->withFieldName('price') + ->withFieldSourcePath('price') + ->withSourceData($price) + ->withConvertedData($converted) + ->build(EmptyNecessaryFieldRunLog::class) + ); continue; } @@ -1492,14 +1502,14 @@ private function createMainCategoriesMapping(array $categories): array DefaultEntities::CATEGORY, $category['categoryId'], $this->context - )['entityUuid']; + )['entityId']; $salesChannelId = $this->mappingService->getOrCreateMapping( $this->connectionId, DefaultEntities::SALES_CHANNEL, $category['shopId'], $this->context - )['entityUuid']; + )['entityId']; if (!$categoryId || !$salesChannelId) { continue; @@ -1534,7 +1544,7 @@ private function getCategoryMapping(array $categories): array if ($mapping === null) { continue; } - $categoryMapping[] = ['id' => (string) $mapping['entityUuid']]; + $categoryMapping[] = ['id' => (string) $mapping['entityId']]; $this->mappingIds[] = $mapping['id']; } @@ -1560,7 +1570,7 @@ private function getVisibilities(array $converted, array $shops): array ); if ($mapping !== null) { - $salesChannelUuid = (string) $mapping['entityUuid']; + $salesChannelUuid = (string) $mapping['entityId']; $this->mappingIds[] = $mapping['id']; $mapping = $this->mappingService->getOrCreateMapping( $this->connectionId, @@ -1570,7 +1580,7 @@ private function getVisibilities(array $converted, array $shops): array ); $this->mappingIds[] = $mapping['id']; $visibilities[] = [ - 'id' => (string) $mapping['entityUuid'], + 'id' => (string) $mapping['entityId'], 'productId' => $converted['id'], 'salesChannelId' => $salesChannelUuid, 'visibility' => ProductVisibilityDefinition::VISIBILITY_ALL, diff --git a/src/Profile/Shopware/Converter/ProductOptionRelationConverter.php b/src/Profile/Shopware/Converter/ProductOptionRelationConverter.php index 587823a86..2da20c296 100644 --- a/src/Profile/Shopware/Converter/ProductOptionRelationConverter.php +++ b/src/Profile/Shopware/Converter/ProductOptionRelationConverter.php @@ -9,6 +9,7 @@ use Shopware\Core\Framework\Context; use Shopware\Core\Framework\Log\Package; +use Shopware\Core\Framework\Util\Hasher; use SwagMigrationAssistant\Migration\Converter\ConvertStruct; use SwagMigrationAssistant\Migration\DataSelection\DefaultEntities; use SwagMigrationAssistant\Migration\MigrationContextInterface; @@ -34,10 +35,7 @@ public function convert(array $data, Context $context, MigrationContextInterface $this->originalData = $data; $connection = $migrationContext->getConnection(); - $this->connectionId = ''; - if ($connection !== null) { - $this->connectionId = $connection->getId(); - } + $this->connectionId = $connection->getId(); $productContainerMapping = $this->mappingService->getMapping( $this->connectionId, @@ -46,29 +44,16 @@ public function convert(array $data, Context $context, MigrationContextInterface $context ); - if ($productContainerMapping === null) { - return new ConvertStruct(null, $this->originalData); - } - $this->mappingIds[] = $productContainerMapping['id']; - - $optionMapping = $this->mappingService->getMapping( - $this->connectionId, - DefaultEntities::PROPERTY_GROUP_OPTION, - \hash('md5', \mb_strtolower($data['name'] . '_' . $data['group']['name'])), - $context - ); - - if ($optionMapping === null) { - return new ConvertStruct(null, $this->originalData); + $relationMapping = null; + if ($productContainerMapping !== null) { + $this->mappingIds[] = $productContainerMapping['id']; + $relationMapping = $this->mappingService->getMapping( + $this->connectionId, + DefaultEntities::PRODUCT_PROPERTY, + $data['id'] . '_' . $productContainerMapping['entityId'], + $context + ); } - $this->mappingIds[] = $optionMapping['id']; - - $relationMapping = $this->mappingService->getMapping( - $this->connectionId, - DefaultEntities::PRODUCT_PROPERTY, - $data['id'] . '_' . $productContainerMapping['entityUuid'], - $context - ); // use "old" relation mapping if exists < v.1.3 if ($relationMapping !== null) { @@ -79,7 +64,7 @@ public function convert(array $data, Context $context, MigrationContextInterface $context, null, null, - $relationMapping['entityUuid'] + $relationMapping['entityId'] ); } else { $this->mainMapping = $this->mappingService->getOrCreateMapping( @@ -90,12 +75,27 @@ public function convert(array $data, Context $context, MigrationContextInterface ); } + $optionMapping = $this->mappingService->getMapping( + $this->connectionId, + DefaultEntities::PROPERTY_GROUP_OPTION, + Hasher::hash(\mb_strtolower($data['name'] . '_' . $data['group']['name']), 'md5'), + $context + ); + $converted = []; - $converted['id'] = $productContainerMapping['entityUuid']; - $converted['configuratorSettings'][] = [ - 'id' => $this->mainMapping['entityUuid'], - 'optionId' => $optionMapping['entityUuid'], - ]; + + if ($optionMapping !== null) { + $this->mappingIds[] = $optionMapping['id']; + $converted['configuratorSettings'][] = [ + 'id' => $this->mainMapping['entityId'], + 'optionId' => $optionMapping['entityId'], + ]; + } + + if (isset($productContainerMapping['entityId'])) { + $converted['id'] = $productContainerMapping['entityId']; + } + $this->updateMainMapping($migrationContext, $context); return new ConvertStruct($converted, null, $this->mainMapping['id'] ?? null); diff --git a/src/Profile/Shopware/Converter/ProductPropertyRelationConverter.php b/src/Profile/Shopware/Converter/ProductPropertyRelationConverter.php index e1b25099c..75d6c9289 100644 --- a/src/Profile/Shopware/Converter/ProductPropertyRelationConverter.php +++ b/src/Profile/Shopware/Converter/ProductPropertyRelationConverter.php @@ -9,6 +9,7 @@ use Shopware\Core\Framework\Context; use Shopware\Core\Framework\Log\Package; +use Shopware\Core\Framework\Util\Hasher; use SwagMigrationAssistant\Migration\Converter\ConvertStruct; use SwagMigrationAssistant\Migration\DataSelection\DefaultEntities; use SwagMigrationAssistant\Migration\MigrationContextInterface; @@ -37,11 +38,9 @@ public function convert(array $data, Context $context, MigrationContextInterface $this->originalData = $data; $connection = $migrationContext->getConnection(); - $this->connectionId = ''; - if ($connection !== null) { - $this->connectionId = $connection->getId(); - } + $this->connectionId = $connection->getId(); + $converted = []; $productMapping = $this->mappingService->getMapping( $this->connectionId, DefaultEntities::PRODUCT_CONTAINER, @@ -56,23 +55,28 @@ public function convert(array $data, Context $context, MigrationContextInterface $data['productId'], $context ); + } - if ($productMapping === null) { - return new ConvertStruct(null, $this->originalData); - } + if ($productMapping !== null) { + $this->mappingIds[] = $productMapping['id']; + $converted['id'] = $productMapping['entityId']; } - $this->mappingIds[] = $productMapping['id']; + $optionMapping = $this->mappingService->getMapping( $this->connectionId, DefaultEntities::PROPERTY_GROUP_OPTION, - \hash('md5', \mb_strtolower($data['name'] . '_' . $data['group']['name'])), + Hasher::hash(\mb_strtolower($data['name'] . '_' . $data['group']['name']), 'md5'), $context ); - if ($optionMapping === null) { - return new ConvertStruct(null, $this->originalData); + if ($optionMapping !== null) { + $this->mappingIds[] = $optionMapping['id']; + + $converted['properties'][] = [ + 'id' => $optionMapping['entityId'], + ]; } - $this->mappingIds[] = $optionMapping['id']; + $this->mainMapping = $this->mappingService->getOrCreateMapping( $this->connectionId, DefaultEntities::PRODUCT_PROPERTY_RELATION, @@ -80,12 +84,6 @@ public function convert(array $data, Context $context, MigrationContextInterface $context ); - $converted = []; - $converted['id'] = $productMapping['entityUuid']; - $converted['properties'][] = [ - 'id' => $optionMapping['entityUuid'], - ]; - $this->updateMainMapping($migrationContext, $context); return new ConvertStruct($converted, null, $this->mainMapping['id'] ?? null); diff --git a/src/Profile/Shopware/Converter/ProductReviewConverter.php b/src/Profile/Shopware/Converter/ProductReviewConverter.php index ced4cac7c..c0efbc6bd 100644 --- a/src/Profile/Shopware/Converter/ProductReviewConverter.php +++ b/src/Profile/Shopware/Converter/ProductReviewConverter.php @@ -11,8 +11,6 @@ use Shopware\Core\Framework\Log\Package; use SwagMigrationAssistant\Migration\Converter\ConvertStruct; use SwagMigrationAssistant\Migration\DataSelection\DefaultEntities; -use SwagMigrationAssistant\Migration\Logging\Log\AssociationRequiredMissingLog; -use SwagMigrationAssistant\Migration\Logging\Log\EmptyNecessaryFieldRunLog; use SwagMigrationAssistant\Migration\Logging\LoggingServiceInterface; use SwagMigrationAssistant\Migration\Mapping\Lookup\LanguageLookup; use SwagMigrationAssistant\Migration\Mapping\MappingServiceInterface; @@ -21,14 +19,6 @@ #[Package('fundamentals@after-sales')] abstract class ProductReviewConverter extends ShopwareConverter { - /** - * @var list - */ - protected array $requiredDataFieldKeys = [ - '_locale', - 'articleID', - ]; - public function __construct( MappingServiceInterface $mappingService, LoggingServiceInterface $loggingService, @@ -39,27 +29,15 @@ public function __construct( public function convert(array $data, Context $context, MigrationContextInterface $migrationContext): ConvertStruct { - $fields = $this->checkForEmptyRequiredDataFields($data, $this->requiredDataFieldKeys); - - if (!empty($fields)) { - $this->loggingService->addLogEntry(new EmptyNecessaryFieldRunLog( - $migrationContext->getRunUuid(), - DefaultEntities::PRODUCT_REVIEW, - $data['id'], - \implode(',', $fields) - )); + $connection = $migrationContext->getConnection(); + $connectionId = $connection->getId(); - return new ConvertStruct(null, $data); - } $this->generateChecksum($data); - $originalData = $data; - $mainLocale = $data['_locale']; - unset($data['_locale']); - $connection = $migrationContext->getConnection(); - $connectionId = ''; - if ($connection !== null) { - $connectionId = $connection->getId(); + $mainLocale = null; + if (isset($data['_locale'])) { + $mainLocale = $data['_locale']; + unset($data['_locale']); } $converted = []; @@ -70,13 +48,14 @@ public function convert(array $data, Context $context, MigrationContextInterface $context, $this->checksum ); - $converted['id'] = $this->mainMapping['entityUuid']; + + $converted['id'] = $this->mainMapping['entityId']; unset($data['id']); $mapping = $this->mappingService->getMapping( $connectionId, DefaultEntities::PRODUCT_MAIN, - $data['articleID'], + $data['articleID'] ?? '', $context ); @@ -84,26 +63,16 @@ public function convert(array $data, Context $context, MigrationContextInterface $mapping = $this->mappingService->getMapping( $connectionId, DefaultEntities::PRODUCT_CONTAINER, - $data['articleID'], + $data['articleID'] ?? '', $context ); + } - if ($mapping === null) { - $this->loggingService->addLogEntry( - new AssociationRequiredMissingLog( - $migrationContext->getRunUuid(), - DefaultEntities::PRODUCT, - $data['articleID'], - DefaultEntities::PRODUCT_REVIEW - ) - ); - - return new ConvertStruct(null, $originalData); - } + if ($mapping !== null) { + $converted['productId'] = $mapping['entityId']; + $this->mappingIds[] = $mapping['id']; + unset($data['articleID']); } - $converted['productId'] = $mapping['entityUuid']; - $this->mappingIds[] = $mapping['id']; - unset($data['articleID']); if (isset($data['email'])) { $mapping = $this->mappingService->getMapping( @@ -114,10 +83,11 @@ public function convert(array $data, Context $context, MigrationContextInterface ); if ($mapping !== null) { - $converted['customerId'] = $mapping['entityUuid']; + $converted['customerId'] = $mapping['entityId']; $this->mappingIds[] = $mapping['id']; } } + $this->convertValue($converted, 'externalEmail', $data, 'email'); $this->convertValue($converted, 'externalUser', $data, 'name'); @@ -129,35 +99,13 @@ public function convert(array $data, Context $context, MigrationContextInterface $context ); - if ($mapping === null) { - $this->loggingService->addLogEntry( - new AssociationRequiredMissingLog( - $migrationContext->getRunUuid(), - DefaultEntities::SALES_CHANNEL, - $shopId, - DefaultEntities::PRODUCT_REVIEW - ) - ); - - return new ConvertStruct(null, $originalData); + if ($mapping !== null) { + $converted['salesChannelId'] = $mapping['entityId']; + $this->mappingIds[] = $mapping['id']; + unset($data['shop_id'], $data['mainShopId']); } - $converted['salesChannelId'] = $mapping['entityUuid']; - $this->mappingIds[] = $mapping['id']; - unset($data['shop_id'], $data['mainShopId']); $converted['languageId'] = $this->languageLookup->get($mainLocale, $context); - if ($converted['languageId'] === null) { - $this->loggingService->addLogEntry( - new AssociationRequiredMissingLog( - $migrationContext->getRunUuid(), - DefaultEntities::LANGUAGE, - $mainLocale, - DefaultEntities::PRODUCT_REVIEW - ) - ); - - return new ConvertStruct(null, $originalData); - } $this->convertValue($converted, 'title', $data, 'headline'); if (empty($converted['title'])) { diff --git a/src/Profile/Shopware/Converter/PromotionConverter.php b/src/Profile/Shopware/Converter/PromotionConverter.php index e96286b0f..d79244961 100644 --- a/src/Profile/Shopware/Converter/PromotionConverter.php +++ b/src/Profile/Shopware/Converter/PromotionConverter.php @@ -7,7 +7,10 @@ namespace SwagMigrationAssistant\Profile\Shopware\Converter; +use Shopware\Core\Checkout\Promotion\Aggregate\PromotionCartRule\PromotionCartRuleDefinition; use Shopware\Core\Checkout\Promotion\Aggregate\PromotionDiscount\PromotionDiscountEntity; +use Shopware\Core\Checkout\Promotion\Aggregate\PromotionPersonaRule\PromotionPersonaRuleDefinition; +use Shopware\Core\Checkout\Promotion\PromotionDefinition; use Shopware\Core\Framework\Context; use Shopware\Core\Framework\DataAbstractionLayer\EntityRepository; use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria; @@ -18,6 +21,7 @@ use SwagMigrationAssistant\Migration\Converter\ConvertStruct; use SwagMigrationAssistant\Migration\DataSelection\DefaultEntities; use SwagMigrationAssistant\Migration\Logging\Log\AssociationRequiredMissingLog; +use SwagMigrationAssistant\Migration\Logging\Log\Builder\MigrationLogBuilder; use SwagMigrationAssistant\Migration\Logging\LoggingServiceInterface; use SwagMigrationAssistant\Migration\Mapping\MappingServiceInterface; use SwagMigrationAssistant\Migration\MigrationContextInterface; @@ -34,8 +38,6 @@ abstract class PromotionConverter extends ShopwareConverter */ private array $productUuids; - private string $runId; - /** * @param EntityRepository $salesChannelRepository */ @@ -56,13 +58,9 @@ public function convert(array $data, Context $context, MigrationContextInterface { $this->generateChecksum($data); $this->context = $context; - $this->runId = $migrationContext->getRunUuid(); $connection = $migrationContext->getConnection(); - $this->connectionId = ''; - if ($connection !== null) { - $this->connectionId = $connection->getId(); - } + $this->connectionId = $connection->getId(); $converted = []; $this->mainMapping = $this->mappingService->getOrCreateMapping( @@ -72,7 +70,7 @@ public function convert(array $data, Context $context, MigrationContextInterface $context, $this->checksum ); - $converted['id'] = $this->mainMapping['entityUuid']; + $converted['id'] = $this->mainMapping['entityId']; $converted['active'] = true; $converted['useCodes'] = true; $converted['useIndividualCodes'] = false; @@ -86,12 +84,12 @@ public function convert(array $data, Context $context, MigrationContextInterface $this->setIndividualCodes($data, $converted); } - $this->setSalesChannel($data, $converted); - $this->setProductNumbers($data); + $this->setSalesChannel($data, $converted, $migrationContext); + $this->setProductNumbers($data, $migrationContext); $this->setDiscount($data, $converted); $this->setShippingDiscount($data, $converted); - $this->setCartRule($data, $converted); - $this->setCustomerRule($data, $converted); + $this->setCartRule($data, $converted, $migrationContext); + $this->setCustomerRule($data, $converted, $migrationContext); $this->convertValue($converted, 'name', $data, 'description'); $this->convertValue($converted, 'validFrom', $data, 'valid_from', self::TYPE_DATETIME); @@ -133,7 +131,7 @@ private function setIndividualCodes(array &$data, array &$converted): void ); $newCode = []; - $newCode['id'] = $codeMapping['entityUuid']; + $newCode['id'] = $codeMapping['entityId']; $this->mappingIds[] = $codeMapping['id']; $this->convertValue($newCode, 'code', $code, 'code'); @@ -158,7 +156,7 @@ private function setIndividualCodes(array &$data, array &$converted): void ); if ($customerMapping !== null) { - $newCode['payload']['customerId'] = $customerMapping['entityUuid']; + $newCode['payload']['customerId'] = $customerMapping['entityId']; $this->mappingIds[] = $customerMapping['id']; } } @@ -187,7 +185,7 @@ private function setDiscount(array &$data, array &$converted): void ); $discount = [ - 'id' => $discountMapping['entityUuid'], + 'id' => $discountMapping['entityId'], 'scope' => PromotionDiscountEntity::SCOPE_CART, 'type' => $type, 'value' => (float) $data['value'], @@ -266,20 +264,20 @@ private function getDiscountRule(array $data): ?array $this->mappingIds[] = $orConditionContainerMapping['id']; $rule = [ - 'id' => $ruleMapping['entityUuid'], + 'id' => $ruleMapping['entityId'], 'name' => 'Promotion discount rule: ' . $data['description'], 'priority' => 0, 'conditions' => [ [ - 'id' => $orContainerMapping['entityUuid'], + 'id' => $orContainerMapping['entityId'], 'type' => (new OrRule())->getName(), 'value' => [], ], [ - 'id' => $orConditionContainerMapping['entityUuid'], + 'id' => $orConditionContainerMapping['entityId'], 'type' => (new OrRule())->getName(), - 'parentId' => $orContainerMapping['entityUuid'], + 'parentId' => $orContainerMapping['entityId'], 'value' => [], ], ], @@ -296,9 +294,9 @@ private function getDiscountRule(array $data): ?array $this->mappingIds[] = $conditionMapping['id']; $rule['conditions'][] = [ - 'id' => $conditionMapping['entityUuid'], + 'id' => $conditionMapping['entityId'], 'type' => 'cartLineItem', - 'parentId' => $orConditionContainerMapping['entityUuid'], + 'parentId' => $orConditionContainerMapping['entityId'], 'position' => 1, 'value' => [ 'identifiers' => $this->productUuids, @@ -325,12 +323,12 @@ private function getDiscountRule(array $data): ?array ); $manufacturerRule = [ - 'id' => $manufacturerConditionMapping['entityUuid'], + 'id' => $manufacturerConditionMapping['entityId'], 'type' => 'cartLineItemOfManufacturer', - 'parentId' => $orConditionContainerMapping['entityUuid'], + 'parentId' => $orConditionContainerMapping['entityId'], 'position' => 1, 'value' => [ - 'manufacturerIds' => [$manufacturerMapping['entityUuid']], + 'manufacturerIds' => [$manufacturerMapping['entityId']], 'operator' => '=', ], ]; @@ -350,7 +348,7 @@ private function getDiscountRule(array $data): ?array /** * @param array $data */ - private function setProductNumbers(array &$data): void + private function setProductNumbers(array &$data, MigrationContextInterface $migrationContext): void { if (!isset($data['restrictarticles'])) { return; @@ -370,18 +368,18 @@ private function setProductNumbers(array &$data): void if ($productMapping === null) { $this->loggingService->addLogEntry( - new AssociationRequiredMissingLog( - $this->runId, - DefaultEntities::PRODUCT, - $productNumber, - DefaultEntities::PROMOTION - ) + MigrationLogBuilder::fromMigrationContext($migrationContext) + ->withEntityName(PromotionDefinition::ENTITY_NAME) + ->withFieldName('productId') + ->withFieldSourcePath('restrictarticles') + ->withSourceData($data) + ->build(AssociationRequiredMissingLog::class) ); continue; } - $this->productUuids[] = (string) $productMapping['entityUuid']; + $this->productUuids[] = (string) $productMapping['entityId']; $this->mappingIds[] = $productMapping['id']; unset($data['restrictarticles']); } @@ -392,7 +390,7 @@ private function setProductNumbers(array &$data): void * @param array $data * @param array $converted */ - private function setCartRule(array &$data, array &$converted): void + private function setCartRule(array &$data, array &$converted, MigrationContextInterface $migrationContext): void { if (empty($this->productUuids) && !isset($data['bindtosupplier']) && !isset($data['minimumcharge'])) { return; @@ -431,20 +429,20 @@ private function setCartRule(array &$data, array &$converted): void $this->mappingIds[] = $andContainerMapping['id']; $rule = [ - 'id' => $ruleMapping['entityUuid'], + 'id' => $ruleMapping['entityId'], 'name' => 'Promotion cart rule: ' . $data['description'], 'priority' => 0, 'conditions' => [ [ - 'id' => $orContainerMapping['entityUuid'], + 'id' => $orContainerMapping['entityId'], 'type' => (new OrRule())->getName(), 'value' => [], ], [ - 'id' => $andContainerMapping['entityUuid'], + 'id' => $andContainerMapping['entityId'], 'type' => (new AndRule())->getName(), - 'parentId' => $orContainerMapping['entityUuid'], + 'parentId' => $orContainerMapping['entityId'], 'value' => [], ], ], @@ -461,9 +459,9 @@ private function setCartRule(array &$data, array &$converted): void $this->mappingIds[] = $conditionMapping['id']; $rule['conditions'][] = [ - 'id' => $conditionMapping['entityUuid'], + 'id' => $conditionMapping['entityId'], 'type' => 'cartLineItem', - 'parentId' => $andContainerMapping['entityUuid'], + 'parentId' => $andContainerMapping['entityId'], 'position' => 1, 'value' => [ 'identifiers' => $this->productUuids, @@ -490,12 +488,12 @@ private function setCartRule(array &$data, array &$converted): void ); $manufacturerRule = [ - 'id' => $manufacturerConditionMapping['entityUuid'], + 'id' => $manufacturerConditionMapping['entityId'], 'type' => 'cartLineItemOfManufacturer', - 'parentId' => $andContainerMapping['entityUuid'], + 'parentId' => $andContainerMapping['entityId'], 'position' => 1, 'value' => [ - 'manufacturerIds' => [$manufacturerMapping['entityUuid']], + 'manufacturerIds' => [$manufacturerMapping['entityId']], 'operator' => '=', ], ]; @@ -505,12 +503,12 @@ private function setCartRule(array &$data, array &$converted): void $oneRuleAdded = true; } else { $this->loggingService->addLogEntry( - new AssociationRequiredMissingLog( - $this->runId, - DefaultEntities::PRODUCT_MANUFACTURER, - $data['bindtosupplier'], - DefaultEntities::PROMOTION_DISCOUNT - ) + MigrationLogBuilder::fromMigrationContext($migrationContext) + ->withEntityName(PromotionCartRuleDefinition::ENTITY_NAME) + ->withFieldName('rule.value.manufacturerId') + ->withFieldSourcePath('bindtosupplier') + ->withSourceData($data) + ->build(AssociationRequiredMissingLog::class) ); } } @@ -524,9 +522,9 @@ private function setCartRule(array &$data, array &$converted): void ); $cartGoodsPriceRule = [ - 'id' => $cartGoodsPriceConditionMapping['entityUuid'], + 'id' => $cartGoodsPriceConditionMapping['entityId'], 'type' => 'cartGoodsPrice', - 'parentId' => $andContainerMapping['entityUuid'], + 'parentId' => $andContainerMapping['entityId'], 'position' => 1, 'value' => [ 'amount' => (float) $data['minimumcharge'], @@ -548,7 +546,7 @@ private function setCartRule(array &$data, array &$converted): void * @param array $data * @param array $converted */ - private function setSalesChannel(array &$data, array &$converted): void + private function setSalesChannel(array &$data, array &$converted, MigrationContextInterface $migrationContext): void { if (isset($data['subshopID'])) { $salesChannelMapping = $this->mappingService->getMapping( @@ -560,12 +558,13 @@ private function setSalesChannel(array &$data, array &$converted): void if ($salesChannelMapping === null) { $this->loggingService->addLogEntry( - new AssociationRequiredMissingLog( - $this->runId, - DefaultEntities::SALES_CHANNEL, - $data['subshopID'], - DefaultEntities::PROMOTION - ) + MigrationLogBuilder::fromMigrationContext($migrationContext) + ->withEntityName(PromotionDefinition::ENTITY_NAME) + ->withFieldName('salesChannelId') + ->withFieldSourcePath('subshopID') + ->withSourceData($data) + ->withConvertedData($converted) + ->build(AssociationRequiredMissingLog::class) ); return; @@ -581,8 +580,8 @@ private function setSalesChannel(array &$data, array &$converted): void $this->mappingIds[] = $salesChannelRelationMapping['id']; $converted['salesChannels'][] = [ - 'id' => $salesChannelRelationMapping['entityUuid'], - 'salesChannelId' => $salesChannelMapping['entityUuid'], + 'id' => $salesChannelRelationMapping['entityId'], + 'salesChannelId' => $salesChannelMapping['entityId'], 'priority' => 0, ]; unset($data['subshopID']); @@ -605,7 +604,7 @@ private function setSalesChannel(array &$data, array &$converted): void $this->mappingIds[] = $salesChannelRelationMapping['id']; $converted['salesChannels'][] = [ - 'id' => $salesChannelRelationMapping['entityUuid'], + 'id' => $salesChannelRelationMapping['entityId'], 'salesChannelId' => $salesChannelId, 'priority' => $priority++, ]; @@ -617,7 +616,7 @@ private function setSalesChannel(array &$data, array &$converted): void * @param array $data * @param array $converted */ - private function setCustomerRule(array &$data, array &$converted): void + private function setCustomerRule(array &$data, array &$converted, MigrationContextInterface $migrationContext): void { if (!isset($data['customergroup'])) { return; @@ -631,12 +630,15 @@ private function setCustomerRule(array &$data, array &$converted): void ); if ($customerGroupMapping === null) { - $this->loggingService->addLogEntry(new AssociationRequiredMissingLog( - $this->runId, - DefaultEntities::CUSTOMER_GROUP, - $data['customergroup'], - DefaultEntities::PROMOTION - )); + $this->loggingService->addLogEntry( + MigrationLogBuilder::fromMigrationContext($migrationContext) + ->withEntityName(PromotionPersonaRuleDefinition::ENTITY_NAME) + ->withFieldName('rule.value.customerGroupId') + ->withFieldSourcePath('customergroup') + ->withSourceData($data) + ->withConvertedData($converted) + ->build(AssociationRequiredMissingLog::class) + ); return; } @@ -683,30 +685,30 @@ private function setCustomerRule(array &$data, array &$converted): void $this->mappingIds[] = $conditionMapping['id']; $rule = [ - 'id' => $ruleMapping['entityUuid'], + 'id' => $ruleMapping['entityId'], 'name' => 'Promotion customer rule: ' . $data['description'], 'priority' => 0, 'conditions' => [ [ - 'id' => $orContainerMapping['entityUuid'], + 'id' => $orContainerMapping['entityId'], 'type' => (new OrRule())->getName(), 'value' => [], ], [ - 'id' => $andContainerMapping['entityUuid'], + 'id' => $andContainerMapping['entityId'], 'type' => (new AndRule())->getName(), - 'parentId' => $orContainerMapping['entityUuid'], + 'parentId' => $orContainerMapping['entityId'], 'value' => [], ], [ - 'id' => $conditionMapping['entityUuid'], + 'id' => $conditionMapping['entityId'], 'type' => 'customerCustomerGroup', - 'parentId' => $andContainerMapping['entityUuid'], + 'parentId' => $andContainerMapping['entityId'], 'position' => 1, 'value' => [ 'customerGroupIds' => [ - $customerGroupMapping['entityUuid'], + $customerGroupMapping['entityId'], ], 'operator' => '=', ], @@ -736,7 +738,7 @@ private function setShippingDiscount(array $data, array &$converted): void ); $deliveryDiscount = [ - 'id' => $deliveryDiscountMapping['entityUuid'], + 'id' => $deliveryDiscountMapping['entityId'], 'scope' => PromotionDiscountEntity::SCOPE_DELIVERY, 'type' => PromotionDiscountEntity::TYPE_PERCENTAGE, 'value' => 100, diff --git a/src/Profile/Shopware/Converter/PropertyGroupOptionConverter.php b/src/Profile/Shopware/Converter/PropertyGroupOptionConverter.php index 4b07125d6..9dd355a16 100644 --- a/src/Profile/Shopware/Converter/PropertyGroupOptionConverter.php +++ b/src/Profile/Shopware/Converter/PropertyGroupOptionConverter.php @@ -7,12 +7,14 @@ namespace SwagMigrationAssistant\Profile\Shopware\Converter; +use Shopware\Core\Content\Property\PropertyGroupDefinition; use Shopware\Core\Framework\Context; use Shopware\Core\Framework\Log\Package; +use Shopware\Core\Framework\Util\Hasher; use SwagMigrationAssistant\Migration\Converter\ConvertStruct; use SwagMigrationAssistant\Migration\DataSelection\DefaultEntities; -use SwagMigrationAssistant\Migration\Logging\Log\CannotConvertChildEntity; -use SwagMigrationAssistant\Migration\Logging\Log\EmptyNecessaryFieldRunLog; +use SwagMigrationAssistant\Migration\Logging\Log\Builder\MigrationLogBuilder; +use SwagMigrationAssistant\Migration\Logging\Log\CannotConvertChildEntityLog; use SwagMigrationAssistant\Migration\Logging\LoggingServiceInterface; use SwagMigrationAssistant\Migration\Mapping\Lookup\LanguageLookup; use SwagMigrationAssistant\Migration\Mapping\MappingServiceInterface; @@ -47,7 +49,7 @@ public function getSourceIdentifier(array $data): string $group = $data['group']['name']; } - return \hash('md5', \mb_strtolower($data['name'] . '_' . $group . '_' . $data['type'])); + return Hasher::hash(\mb_strtolower($data['name'] . '_' . $group . '_' . $data['type']), 'md5'); } public function getMediaUuids(array $converted): ?array @@ -72,45 +74,31 @@ public function convert(array $data, Context $context, MigrationContextInterface $this->runId = $migrationContext->getRunUuid(); $connection = $migrationContext->getConnection(); - $this->connectionId = ''; - if ($connection !== null) { - $this->connectionId = $connection->getId(); - } - - if (!isset($data['group']['name'])) { - $this->loggingService->addLogEntry(new EmptyNecessaryFieldRunLog( - $this->runId, + $this->connectionId = $connection->getId(); + $converted = []; + if (isset($data['group']['name'])) { + $mapping = $this->mappingService->getOrCreateMapping( + $this->connectionId, DefaultEntities::PROPERTY_GROUP_OPTION, - $data['id'], - 'group' - )); - - return new ConvertStruct(null, $data); + Hasher::hash(\mb_strtolower($data['name'] . '_' . $data['group']['name']), 'md5'), + $context + ); + $this->mappingIds[] = $mapping['id']; + + $propertyGroupMapping = $this->mappingService->getOrCreateMapping( + $this->connectionId, + DefaultEntities::PROPERTY_GROUP, + Hasher::hash(\mb_strtolower($data['group']['name']), 'md5'), + $context + ); + $this->mappingIds[] = $propertyGroupMapping['id']; + + $converted['id'] = $mapping['entityId']; + $converted['group'] = [ + 'id' => $propertyGroupMapping['entityId'], + ]; } - $mapping = $this->mappingService->getOrCreateMapping( - $this->connectionId, - DefaultEntities::PROPERTY_GROUP_OPTION, - \hash('md5', \mb_strtolower($data['name'] . '_' . $data['group']['name'])), - $context - ); - $this->mappingIds[] = $mapping['id']; - - $propertyGroupMapping = $this->mappingService->getOrCreateMapping( - $this->connectionId, - DefaultEntities::PROPERTY_GROUP, - \hash('md5', \mb_strtolower($data['group']['name'])), - $context - ); - $this->mappingIds[] = $propertyGroupMapping['id']; - - $converted = [ - 'id' => $mapping['entityUuid'], - 'group' => [ - 'id' => $propertyGroupMapping['entityUuid'], - ], - ]; - $this->createAndDeleteNecessaryMappings($data, $converted); if (isset($data['media'])) { @@ -132,12 +120,14 @@ public function convert(array $data, Context $context, MigrationContextInterface protected function setMedia(array &$converted, array $data): void { if (!isset($data['media']['id'])) { - $this->loggingService->addLogEntry(new CannotConvertChildEntity( - $this->runId, - 'property_group_option_media', - DefaultEntities::PROPERTY_GROUP_OPTION, - $data['id'] - )); + $this->loggingService->addLogEntry( + MigrationLogBuilder::fromMigrationContext($this->migrationContext) + ->withEntityName(PropertyGroupDefinition::ENTITY_NAME) + ->withFieldName('media.id') + ->withFieldSourcePath('media.id') + ->withSourceData($data) + ->build(CannotConvertChildEntityLog::class) + ); return; } @@ -149,7 +139,7 @@ protected function setMedia(array &$converted, array $data): void $data['media']['id'], $this->context ); - $newMedia['id'] = $mapping['entityUuid']; + $newMedia['id'] = $mapping['entityId']; $this->mappingIds[] = $mapping['id']; if (empty($data['media']['name'])) { @@ -179,7 +169,7 @@ protected function setMedia(array &$converted, array $data): void ); if ($albumMapping !== null) { - $newMedia['mediaFolderId'] = $albumMapping['entityUuid']; + $newMedia['mediaFolderId'] = $albumMapping['entityId']; $this->mappingIds[] = $albumMapping['id']; } @@ -213,7 +203,7 @@ protected function setMediaTranslation(array &$media, array $data): void $data['media']['id'] . ':' . $this->locale, $this->context ); - $localeTranslation['id'] = $mapping['entityUuid']; + $localeTranslation['id'] = $mapping['entityId']; $this->mappingIds[] = $mapping['id']; $languageUuid = $this->languageLookup->get($this->locale, $this->context); @@ -254,7 +244,7 @@ protected function createAndDeleteNecessaryMappings(array $data, array $converte $this->mainMapping = $this->mappingService->getOrCreateMapping( $this->connectionId, DefaultEntities::PROPERTY_GROUP_OPTION, - \hash('md5', \mb_strtolower($data['name'] . '_' . $data['group']['name'] . '_' . $data['type'])), + Hasher::hash(\mb_strtolower($data['name'] . '_' . $data['group']['name'] . '_' . $data['type']), 'md5'), $this->context, $this->checksum ); @@ -262,7 +252,7 @@ protected function createAndDeleteNecessaryMappings(array $data, array $converte $mapping = $this->mappingService->getOrCreateMapping( $this->connectionId, DefaultEntities::PROPERTY_GROUP_OPTION, - \hash('md5', \mb_strtolower($data['group']['name'] . '_' . $data['type'])), + Hasher::hash(\mb_strtolower($data['group']['name'] . '_' . $data['type']), 'md5'), $this->context ); $this->mappingIds[] = $mapping['id']; diff --git a/src/Profile/Shopware/Converter/SalesChannelConverter.php b/src/Profile/Shopware/Converter/SalesChannelConverter.php index 6494fa260..037c89f3e 100644 --- a/src/Profile/Shopware/Converter/SalesChannelConverter.php +++ b/src/Profile/Shopware/Converter/SalesChannelConverter.php @@ -20,15 +20,15 @@ use Shopware\Core\Framework\Log\Package; use Shopware\Core\System\Country\CountryCollection; use Shopware\Core\System\SalesChannel\SalesChannelCollection; +use Shopware\Core\System\SalesChannel\SalesChannelDefinition; use SwagMigrationAssistant\Migration\Converter\ConvertStruct; use SwagMigrationAssistant\Migration\DataSelection\DefaultEntities; -use SwagMigrationAssistant\Migration\Logging\Log\AssociationRequiredMissingLog; +use SwagMigrationAssistant\Migration\Logging\Log\Builder\MigrationLogBuilder; use SwagMigrationAssistant\Migration\Logging\LoggingServiceInterface; use SwagMigrationAssistant\Migration\Mapping\Lookup\CurrencyLookup; use SwagMigrationAssistant\Migration\Mapping\Lookup\LanguageLookup; use SwagMigrationAssistant\Migration\Mapping\MappingServiceInterface; use SwagMigrationAssistant\Migration\MigrationContextInterface; -use SwagMigrationAssistant\Profile\Shopware\DataSelection\DataSet\SalesChannelDataSet; use SwagMigrationAssistant\Profile\Shopware\Logging\Log\DeactivatedPackLanguageLog; use SwagMigrationAssistant\Profile\Shopware\Premapping\PaymentMethodReader; @@ -72,10 +72,7 @@ public function convert(array $data, Context $context, MigrationContextInterface $this->oldIdentifier = $data['id']; $connection = $migrationContext->getConnection(); - $this->connectionId = ''; - if ($connection !== null) { - $this->connectionId = $connection->getId(); - } + $this->connectionId = $connection->getId(); $converted = []; $this->mainMapping = $this->mappingService->getOrCreateMapping( @@ -85,7 +82,7 @@ public function convert(array $data, Context $context, MigrationContextInterface $context, $this->checksum ); - $converted['id'] = (string) $this->mainMapping['entityUuid']; + $converted['id'] = (string) $this->mainMapping['entityId']; if (isset($data['children']) && \count($data['children']) > 0) { $this->setRelationMappings($data['children']); @@ -98,40 +95,21 @@ public function convert(array $data, Context $context, MigrationContextInterface $context ); - if ($customerGroupMapping === null) { - $this->loggingService->addLogEntry( - new AssociationRequiredMissingLog( - $migrationContext->getRunUuid(), - DefaultEntities::CUSTOMER_GROUP, - $data['customer_group_id'], - DefaultEntities::SALES_CHANNEL - ) - ); - - return new ConvertStruct(null, $data); + if ($customerGroupMapping !== null) { + $this->mappingIds[] = $customerGroupMapping['id']; + $converted['customerGroupId'] = $customerGroupMapping['entityId']; } - $customerGroupUuid = $customerGroupMapping['entityUuid']; - $this->mappingIds[] = $customerGroupMapping['id']; - $converted['customerGroupId'] = $customerGroupUuid; $languageUuid = $this->languageLookup->get($data['locale'], $context); - if ($languageUuid === null) { - $this->loggingService->addLogEntry( - new AssociationRequiredMissingLog( - $migrationContext->getRunUuid(), - DefaultEntities::LANGUAGE, - $data['locale'], - DefaultEntities::SALES_CHANNEL - ) - ); - - return new ConvertStruct(null, $data); + if ($languageUuid !== null) { + $converted['languageId'] = $languageUuid; + $converted['languages'] = $this->getSalesChannelLanguages($languageUuid, $data, $context); } - $converted['languageId'] = $languageUuid; - $converted['languages'] = $this->getSalesChannelLanguages($languageUuid, $data, $context); + if (isset($converted['languages'])) { + $this->filterExistingLanguageSalesChannelRelation($converted['id'], $converted['languages']); + } - $this->filterExistingLanguageSalesChannelRelation($converted['id'], $converted['languages']); $this->filterDisabledPackLanguages($converted); if (empty($converted['languages'])) { @@ -139,26 +117,15 @@ public function convert(array $data, Context $context, MigrationContextInterface } $currencyUuid = $this->currencyLookup->get($data['currency'], $context); - if ($currencyUuid === null) { - $this->loggingService->addLogEntry( - new AssociationRequiredMissingLog( - $migrationContext->getRunUuid(), - DefaultEntities::CURRENCY, - $data['currency'], - DefaultEntities::SALES_CHANNEL - ) - ); - - return new ConvertStruct(null, $data); + if ($currencyUuid !== null) { + $converted['currencyId'] = $currencyUuid; + $converted['currencies'] = [ + [ + 'id' => $currencyUuid, + ], + ]; } - $converted['currencyId'] = $currencyUuid; - $converted['currencies'] = [ - [ - 'id' => $currencyUuid, - ], - ]; - $categoryMapping = $this->mappingService->getMapping( $this->connectionId, DefaultEntities::CATEGORY, @@ -166,21 +133,10 @@ public function convert(array $data, Context $context, MigrationContextInterface $context ); - if ($categoryMapping === null) { - $this->loggingService->addLogEntry( - new AssociationRequiredMissingLog( - $migrationContext->getRunUuid(), - DefaultEntities::CATEGORY, - $data['category_id'], - DefaultEntities::SALES_CHANNEL - ) - ); - - return new ConvertStruct(null, $data); + if ($categoryMapping !== null) { + $this->mappingIds[] = $categoryMapping['id']; + $converted['navigationCategoryId'] = $categoryMapping['entityId']; } - $categoryUuid = $categoryMapping['entityUuid']; - $this->mappingIds[] = $categoryMapping['id']; - $converted['navigationCategoryId'] = $categoryUuid; $countryUuid = $this->getFirstActiveCountryId(); $converted['countryId'] = $countryUuid; @@ -272,7 +228,7 @@ protected function setSalesChannelTranslation(array &$salesChannel, array $data) $data['id'] . ':' . $this->mainLocale, $this->context ); - $localeTranslation['id'] = $mapping['entityUuid']; + $localeTranslation['id'] = $mapping['entityId']; $this->mappingIds[] = $mapping['id']; $languageUuid = $this->languageLookup->get($this->mainLocale, $this->context); @@ -299,7 +255,7 @@ protected function getFirstActiveShippingMethodId(): string ); if ($mapping !== null) { - $id = (string) $mapping['entityUuid']; + $id = (string) $mapping['entityId']; } } @@ -324,7 +280,7 @@ protected function getFirstActivePaymentMethodId(): string ); if ($mapping !== null) { - $id = (string) $mapping['entityUuid']; + $id = (string) $mapping['entityId']; } } @@ -392,7 +348,10 @@ protected function filterDisabledPackLanguages(array &$converted): void } $this->loggingService->addLogEntry( - new DeactivatedPackLanguageLog($this->migrationContext->getRunUuid(), SalesChannelDataSet::getEntity(), $this->oldIdentifier, $packLanguageId) + MigrationLogBuilder::fromMigrationContext($this->migrationContext) + ->withEntityName(SalesChannelDefinition::ENTITY_NAME) + ->withFieldName('languageId') + ->build(DeactivatedPackLanguageLog::class) ); } } @@ -431,7 +390,7 @@ protected function getSalesChannelLanguages(string $languageUuid, array $data, C */ private function setRelationMappings(array $children): void { - if (!isset($this->mainMapping['entityUuid'])) { + if (!isset($this->mainMapping['entityId'])) { return; } @@ -443,7 +402,7 @@ private function setRelationMappings(array $children): void $this->context, null, null, - $this->mainMapping['entityUuid'] + $this->mainMapping['entityId'] ); $this->mappingIds[] = $mapping['id']; } diff --git a/src/Profile/Shopware/Converter/SeoUrlConverter.php b/src/Profile/Shopware/Converter/SeoUrlConverter.php index 175e84d51..3c3ffde91 100644 --- a/src/Profile/Shopware/Converter/SeoUrlConverter.php +++ b/src/Profile/Shopware/Converter/SeoUrlConverter.php @@ -11,12 +11,10 @@ use Shopware\Core\Framework\Log\Package; use SwagMigrationAssistant\Migration\Converter\ConvertStruct; use SwagMigrationAssistant\Migration\DataSelection\DefaultEntities; -use SwagMigrationAssistant\Migration\Logging\Log\AssociationRequiredMissingLog; use SwagMigrationAssistant\Migration\Logging\LoggingServiceInterface; use SwagMigrationAssistant\Migration\Mapping\Lookup\LanguageLookup; use SwagMigrationAssistant\Migration\Mapping\MappingServiceInterface; use SwagMigrationAssistant\Migration\MigrationContextInterface; -use SwagMigrationAssistant\Profile\Shopware\Logging\Log\UnsupportedSeoUrlType; #[Package('fundamentals@after-sales')] abstract class SeoUrlConverter extends ShopwareConverter @@ -40,13 +38,9 @@ public function __construct( public function convert(array $data, Context $context, MigrationContextInterface $migrationContext): ConvertStruct { $this->generateChecksum($data); - $originalData = $data; $connection = $migrationContext->getConnection(); - $this->connectionId = ''; - if ($connection !== null) { - $this->connectionId = $connection->getId(); - } + $this->connectionId = $connection->getId(); $converted = []; $this->mainMapping = $this->mappingService->getOrCreateMapping( @@ -56,7 +50,7 @@ public function convert(array $data, Context $context, MigrationContextInterface $context, $this->checksum ); - $converted['id'] = $this->mainMapping['entityUuid']; + $converted['id'] = $this->mainMapping['entityId']; unset($data['id']); $mapping = $this->mappingService->getMapping( @@ -66,37 +60,17 @@ public function convert(array $data, Context $context, MigrationContextInterface $context ); - if ($mapping === null) { - $this->loggingService->addLogEntry( - new AssociationRequiredMissingLog( - $migrationContext->getRunUuid(), - DefaultEntities::SALES_CHANNEL, - $data['subshopID'], - DefaultEntities::SEO_URL - ) - ); - - return new ConvertStruct(null, $originalData); + if ($mapping !== null) { + $converted['salesChannelId'] = $mapping['entityId']; + $this->mappingIds[] = $mapping['id']; + unset($data['subshopID']); } - $converted['salesChannelId'] = $mapping['entityUuid']; - $this->mappingIds[] = $mapping['id']; - unset($data['subshopID']); $converted['languageId'] = $this->languageLookup->get($data['_locale'], $context); - if ($converted['languageId'] === null) { - $this->loggingService->addLogEntry( - new AssociationRequiredMissingLog( - $migrationContext->getRunUuid(), - DefaultEntities::LANGUAGE, - $data['_locale'], - DefaultEntities::SEO_URL - ) - ); - - return new ConvertStruct(null, $originalData); + if ($converted['languageId'] !== null) { + $this->mappingIds[] = $converted['languageId']; + unset($data['_locale']); } - $this->mappingIds[] = $converted['languageId']; - unset($data['_locale']); if ($data['type'] === self::TYPE_PRODUCT && isset($data['typeId'])) { $mapping = $this->mappingService->getMapping( @@ -113,25 +87,14 @@ public function convert(array $data, Context $context, MigrationContextInterface $data['typeId'], $context ); - - if ($mapping === null) { - $this->loggingService->addLogEntry( - new AssociationRequiredMissingLog( - $migrationContext->getRunUuid(), - DefaultEntities::PRODUCT, - $data['typeId'], - DefaultEntities::SEO_URL - ) - ); - - return new ConvertStruct(null, $originalData); - } } - $converted['foreignKey'] = $mapping['entityUuid']; - $converted['routeName'] = self::ROUTE_NAME_PRODUCT; - $converted['pathInfo'] = '/detail/' . $mapping['entityUuid']; - $this->mappingIds[] = $mapping['id']; + if ($mapping !== null) { + $converted['foreignKey'] = $mapping['entityId']; + $converted['routeName'] = self::ROUTE_NAME_PRODUCT; + $converted['pathInfo'] = '/detail/' . $mapping['entityId']; + $this->mappingIds[] = $mapping['id']; + } } elseif ($data['type'] === self::TYPE_CATEGORY && isset($data['typeId'])) { $mapping = $this->mappingService->getMapping( $this->connectionId, @@ -140,33 +103,12 @@ public function convert(array $data, Context $context, MigrationContextInterface $context ); - if ($mapping === null) { - $this->loggingService->addLogEntry( - new AssociationRequiredMissingLog( - $migrationContext->getRunUuid(), - DefaultEntities::CATEGORY, - $data['typeId'], - DefaultEntities::SEO_URL - ) - ); - - return new ConvertStruct(null, $originalData); + if ($mapping !== null) { + $converted['foreignKey'] = $mapping['entityId']; + $converted['routeName'] = self::ROUTE_NAME_NAVIGATION; + $converted['pathInfo'] = '/navigation/' . $mapping['entityId']; + $this->mappingIds[] = $mapping['id']; } - $converted['foreignKey'] = $mapping['entityUuid']; - $converted['routeName'] = self::ROUTE_NAME_NAVIGATION; - $converted['pathInfo'] = '/navigation/' . $mapping['entityUuid']; - $this->mappingIds[] = $mapping['id']; - } else { - $this->loggingService->addLogEntry( - new UnsupportedSeoUrlType( - $migrationContext->getRunUuid(), - $data['type'], - DefaultEntities::SEO_URL, - $originalData['id'] - ) - ); - - return new ConvertStruct(null, $originalData); } unset($data['type'], $data['typeId']); diff --git a/src/Profile/Shopware/Converter/ShippingMethodConverter.php b/src/Profile/Shopware/Converter/ShippingMethodConverter.php index 12954c92a..1c9c69d7e 100644 --- a/src/Profile/Shopware/Converter/ShippingMethodConverter.php +++ b/src/Profile/Shopware/Converter/ShippingMethodConverter.php @@ -7,19 +7,23 @@ namespace SwagMigrationAssistant\Profile\Shopware\Converter; +use Shopware\Core\Checkout\Shipping\Aggregate\ShippingMethodPrice\ShippingMethodPriceDefinition; +use Shopware\Core\Checkout\Shipping\ShippingMethodDefinition; use Shopware\Core\Framework\Context; use Shopware\Core\Framework\Log\Package; use Shopware\Core\Framework\Rule\Container\AndRule; use Shopware\Core\Framework\Rule\Container\OrRule; +use Shopware\Core\Framework\Util\Hasher; use SwagMigrationAssistant\Migration\Converter\ConvertStruct; use SwagMigrationAssistant\Migration\DataSelection\DefaultEntities; +use SwagMigrationAssistant\Migration\Logging\Log\Builder\MigrationLogBuilder; use SwagMigrationAssistant\Migration\Logging\Log\EmptyNecessaryFieldRunLog; use SwagMigrationAssistant\Migration\Logging\LoggingServiceInterface; use SwagMigrationAssistant\Migration\Mapping\Lookup\CountryLookup; use SwagMigrationAssistant\Migration\Mapping\Lookup\LanguageLookup; use SwagMigrationAssistant\Migration\Mapping\MappingServiceInterface; use SwagMigrationAssistant\Migration\MigrationContextInterface; -use SwagMigrationAssistant\Profile\Shopware\Logging\Log\UnsupportedShippingCalculationType; +use SwagMigrationAssistant\Profile\Shopware\Logging\Log\UnsupportedShippingCalculationTypeLog; use SwagMigrationAssistant\Profile\Shopware\Logging\Log\UnsupportedShippingPriceLog; use SwagMigrationAssistant\Profile\Shopware\Premapping\DefaultShippingAvailabilityRuleReader; use SwagMigrationAssistant\Profile\Shopware\Premapping\DeliveryTimeReader; @@ -70,13 +74,6 @@ abstract class ShippingMethodConverter extends ShopwareConverter protected string $mainLocale; - /** - * @var array - */ - protected array $requiredDataFields = [ - 'deliveryTimeId' => 'delivery_time', - ]; - public function __construct( MappingServiceInterface $mappingService, LoggingServiceInterface $loggingService, @@ -88,30 +85,20 @@ public function __construct( public function convert(array $data, Context $context, MigrationContextInterface $migrationContext): ConvertStruct { - if (empty($data['id'])) { - $this->loggingService->addLogEntry(new EmptyNecessaryFieldRunLog( - $this->runId, - DefaultEntities::SHIPPING_METHOD, - '', - 'id', - )); - - return new ConvertStruct(null, $data); - } + $connection = $migrationContext->getConnection(); + $this->connectionId = $connection->getId(); $this->generateChecksum($data); $this->context = $context; $this->runId = $migrationContext->getRunUuid(); - $this->oldShippingMethod = $data['id']; - $this->mainLocale = $data['_locale']; + $converted = []; - $connection = $migrationContext->getConnection(); - $this->connectionId = ''; - if ($connection !== null) { - $this->connectionId = $connection->getId(); + if (!empty($data['id'])) { + $this->oldShippingMethod = $data['id']; } - $converted = []; + $this->mainLocale = $data['_locale']; + $this->mainMapping = $this->mappingService->getOrCreateMapping( $this->connectionId, DefaultEntities::SHIPPING_METHOD, @@ -120,7 +107,7 @@ public function convert(array $data, Context $context, MigrationContextInterface $this->checksum ); - $converted['id'] = $this->mainMapping['entityUuid']; + $converted['id'] = $this->mainMapping['entityId']; $defaultDeliveryTimeMapping = $this->mappingService->getMapping( $this->connectionId, @@ -130,7 +117,7 @@ public function convert(array $data, Context $context, MigrationContextInterface ); if ($defaultDeliveryTimeMapping !== null) { - $converted['deliveryTimeId'] = $defaultDeliveryTimeMapping['entityUuid']; + $converted['deliveryTimeId'] = $defaultDeliveryTimeMapping['entityId']; $this->mappingIds[] = $defaultDeliveryTimeMapping['id']; } @@ -141,24 +128,10 @@ public function convert(array $data, Context $context, MigrationContextInterface $this->context ); if ($defaultAvailabilityRuleUuid !== null) { - $converted['availabilityRuleId'] = $defaultAvailabilityRuleUuid['entityUuid']; + $converted['availabilityRuleId'] = $defaultAvailabilityRuleUuid['entityId']; $this->mappingIds[] = $defaultAvailabilityRuleUuid['id']; } - $fields = $this->checkForEmptyRequiredConvertedFields($converted, $this->requiredDataFields); - if (!empty($fields)) { - foreach ($fields as $field) { - $this->loggingService->addLogEntry(new EmptyNecessaryFieldRunLog( - $this->runId, - DefaultEntities::SHIPPING_METHOD, - $this->oldShippingMethod, - $field - )); - } - - return new ConvertStruct(null, $data); - } - $converted['technicalName'] = 'migrated_' . $data['id']; $this->addShippingMethodTranslation($converted, $data); @@ -184,15 +157,18 @@ public function convert(array $data, Context $context, MigrationContextInterface if (!isset($data['calculation']) || !\array_key_exists($data['calculation'], self::CALCULATION_TYPE_MAPPING) ) { - $this->loggingService->addLogEntry(new UnsupportedShippingCalculationType( - $this->runId, - DefaultEntities::SHIPPING_METHOD, - $this->oldShippingMethod, - $data['calculation'] - )); + $this->loggingService->addLogEntry( + MigrationLogBuilder::fromMigrationContext($migrationContext) + ->withEntityName(ShippingMethodDefinition::ENTITY_NAME) + ->withFieldName('prices') + ->withFieldSourcePath('calculation') + ->withSourceData($data) + ->withConvertedData($converted) + ->build(UnsupportedShippingCalculationTypeLog::class) + ); } else { $calculationType = self::CALCULATION_TYPE_MAPPING[$data['calculation']]; - $converted['prices'] = $this->getShippingCosts($data, $calculationType, $priceRule); + $converted['prices'] = $this->getShippingCosts($migrationContext, $data, $calculationType, $priceRule); } } @@ -240,17 +216,6 @@ public function convert(array $data, Context $context, MigrationContextInterface } $this->updateMainMapping($migrationContext, $context); - if (!\is_array($this->mainMapping) || !\array_key_exists('id', $this->mainMapping)) { - $this->loggingService->addLogEntry(new EmptyNecessaryFieldRunLog( - $this->runId, - DefaultEntities::SHIPPING_METHOD, - $this->oldShippingMethod, - 'id', - )); - - return new ConvertStruct(null, $data); - } - return new ConvertStruct($converted, $returnData, $this->mainMapping['id'] ?? null); } @@ -283,7 +248,7 @@ protected function addShippingMethodTranslation(array &$shippingMethod, array $d $data['id'] . ':' . $this->mainLocale, $this->context ); - $localeTranslation['id'] = $mapping['entityUuid']; + $localeTranslation['id'] = $mapping['entityId']; $this->mappingIds[] = $mapping['id']; $languageUuid = $this->languageLookup->get($this->mainLocale, $this->context); @@ -323,7 +288,7 @@ protected function getCustomerGroupCalculationRule(array $data): array 'customerGroupRule_' . $customerGroupId, $this->context ); - $priceRuleUuid = $mapping['entityUuid']; + $priceRuleUuid = $mapping['entityId']; $this->mappingIds[] = $mapping['id']; $mapping = $this->mappingService->getOrCreateMapping( @@ -332,7 +297,7 @@ protected function getCustomerGroupCalculationRule(array $data): array 'customerGroupRule_orContainer_' . $customerGroupId, $this->context ); - $orContainerUuid = $mapping['entityUuid']; + $orContainerUuid = $mapping['entityId']; $this->mappingIds[] = $mapping['id']; $mapping = $this->mappingService->getOrCreateMapping( @@ -341,7 +306,7 @@ protected function getCustomerGroupCalculationRule(array $data): array 'customerGroupRule_andContainer_' . $customerGroupId, $this->context ); - $andContainerUuid = $mapping['entityUuid']; + $andContainerUuid = $mapping['entityId']; $this->mappingIds[] = $mapping['id']; $mapping = $this->mappingService->getOrCreateMapping( @@ -350,7 +315,7 @@ protected function getCustomerGroupCalculationRule(array $data): array 'customerGroupRule_condition_' . $customerGroupId, $this->context ); - $conditionUuid = $mapping['entityUuid']; + $conditionUuid = $mapping['entityId']; $this->mappingIds[] = $mapping['id']; $rule = [ @@ -381,7 +346,7 @@ protected function getCustomerGroupCalculationRule(array $data): array 'position' => 1, 'value' => [ 'customerGroupIds' => [ - $customerGroupMapping['entityUuid'], + $customerGroupMapping['entityId'], ], 'operator' => '=', ], @@ -411,7 +376,7 @@ protected function getSalesChannelCalculationRule(array $data): array return []; } - $salesChannelUuid = $salesChannelMapping['entityUuid']; + $salesChannelUuid = $salesChannelMapping['entityId']; $this->mappingIds[] = $salesChannelMapping['id']; $salesChannelName = $shopId; if (isset($data['shop']['name'])) { @@ -424,7 +389,7 @@ protected function getSalesChannelCalculationRule(array $data): array 'salesChannelRule_' . $shopId, $this->context ); - $priceRuleUuid = (string) $mapping['entityUuid']; + $priceRuleUuid = (string) $mapping['entityId']; $this->mappingIds[] = $mapping['id']; $mapping = $this->mappingService->getOrCreateMapping( @@ -433,7 +398,7 @@ protected function getSalesChannelCalculationRule(array $data): array 'salesChannelRule_orContainer_' . $shopId, $this->context ); - $orContainerUuid = (string) $mapping['entityUuid']; + $orContainerUuid = (string) $mapping['entityId']; $this->mappingIds[] = $mapping['id']; $mapping = $this->mappingService->getOrCreateMapping( @@ -442,7 +407,7 @@ protected function getSalesChannelCalculationRule(array $data): array 'salesChannelRule_andContainer_' . $shopId, $this->context ); - $andContainerUuid = (string) $mapping['entityUuid']; + $andContainerUuid = (string) $mapping['entityId']; $this->mappingIds[] = $mapping['id']; $mapping = $this->mappingService->getOrCreateMapping( @@ -451,7 +416,7 @@ protected function getSalesChannelCalculationRule(array $data): array 'salesChannelRule_condition_' . $shopId, $this->context ); - $conditionUuid = (string) $mapping['entityUuid']; + $conditionUuid = (string) $mapping['entityId']; $this->mappingIds[] = $mapping['id']; $rule = [ @@ -511,7 +476,7 @@ protected function getSalesChannelAndCustomerGroupCalculationRule(array $data): if ($salesChannelMapping === null) { return []; } - $salesChannelUuid = $salesChannelMapping['entityUuid']; + $salesChannelUuid = $salesChannelMapping['entityId']; $this->mappingIds[] = $salesChannelMapping['id']; $customerGroupId = $data['customergroupID']; @@ -526,7 +491,7 @@ protected function getSalesChannelAndCustomerGroupCalculationRule(array $data): return []; } - $customerGroupUuid = $customerGroupMapping['entityUuid']; + $customerGroupUuid = $customerGroupMapping['entityId']; $this->mappingIds[] = $customerGroupMapping['id']; $customerGroupName = $customerGroupId; @@ -545,7 +510,7 @@ protected function getSalesChannelAndCustomerGroupCalculationRule(array $data): 'salesChannelAndCustomerGroupRule_' . $shopId . '_' . $customerGroupId, $this->context ); - $priceRuleUuid = (string) $mapping['entityUuid']; + $priceRuleUuid = (string) $mapping['entityId']; $this->mappingIds[] = $mapping['id']; $mapping = $this->mappingService->getOrCreateMapping( @@ -554,7 +519,7 @@ protected function getSalesChannelAndCustomerGroupCalculationRule(array $data): 'salesChannelAndCustomerGroupRule_orContainer_' . $shopId . '_' . $customerGroupId, $this->context ); - $orContainerUuid = (string) $mapping['entityUuid']; + $orContainerUuid = (string) $mapping['entityId']; $this->mappingIds[] = $mapping['id']; $mapping = $this->mappingService->getOrCreateMapping( @@ -563,7 +528,7 @@ protected function getSalesChannelAndCustomerGroupCalculationRule(array $data): 'salesChannelAndCustomerGroupRule_andContainer_' . $shopId . '_' . $customerGroupId, $this->context ); - $andContainerUuid = (string) $mapping['entityUuid']; + $andContainerUuid = (string) $mapping['entityId']; $this->mappingIds[] = $mapping['id']; $mapping = $this->mappingService->getOrCreateMapping( @@ -572,7 +537,7 @@ protected function getSalesChannelAndCustomerGroupCalculationRule(array $data): 'salesChannelAndCustomerGroupRule_condition_' . $shopId . '_' . $customerGroupId, $this->context ); - $conditionUuid = (string) $mapping['entityUuid']; + $conditionUuid = (string) $mapping['entityId']; $this->mappingIds[] = $mapping['id']; $rule = [ @@ -633,7 +598,7 @@ protected function getSalesChannelAndCustomerGroupCalculationRule(array $data): * * @return list> */ - protected function getShippingCosts(array $data, int $calculationType, ?array $rule): array + protected function getShippingCosts(MigrationContextInterface $migrationContext, array $data, int $calculationType, ?array $rule): array { $shippingCosts = $data['shippingCosts']; $taxRate = 0.0; @@ -644,12 +609,14 @@ protected function getShippingCosts(array $data, int $calculationType, ?array $r $convertedCosts = []; foreach ($shippingCosts as $key => $shippingCost) { if (empty($shippingCost['id'])) { - $this->loggingService->addLogEntry(new EmptyNecessaryFieldRunLog( - $this->runId, - DefaultEntities::SHIPPING_METHOD_PRICE, - $this->oldShippingMethod, - 'id' - )); + $this->loggingService->addLogEntry( + MigrationLogBuilder::fromMigrationContext($migrationContext) + ->withEntityName(ShippingMethodPriceDefinition::ENTITY_NAME) + ->withFieldName('id') + ->withFieldSourcePath('id') + ->withSourceData($data) + ->build(EmptyNecessaryFieldRunLog::class) + ); continue; } @@ -663,7 +630,7 @@ protected function getShippingCosts(array $data, int $calculationType, ?array $r $shippingCost['id'], $this->context ); - $cost['id'] = $mapping['entityUuid']; + $cost['id'] = $mapping['entityId']; $this->mappingIds[] = $mapping['id']; $cost['calculation'] = $calculationType; @@ -679,16 +646,18 @@ protected function getShippingCosts(array $data, int $calculationType, ?array $r } if (!isset($currencyMapping)) { - $this->loggingService->addLogEntry(new EmptyNecessaryFieldRunLog( - $this->runId, - DefaultEntities::SHIPPING_METHOD_PRICE, - $shippingCost['id'], - 'currency' - )); + $this->loggingService->addLogEntry( + MigrationLogBuilder::fromMigrationContext($migrationContext) + ->withEntityName(ShippingMethodPriceDefinition::ENTITY_NAME) + ->withFieldName('currencyId') + ->withFieldSourcePath('currencyShortName') + ->withSourceData($data) + ->build(EmptyNecessaryFieldRunLog::class) + ); continue; } - $currencyUuid = $currencyMapping['entityUuid']; + $currencyUuid = $currencyMapping['entityId']; $this->mappingIds[] = $currencyMapping['id']; $cost['currencyId'] = $currencyUuid; if (isset($shippingCosts[$key + 1])) { @@ -696,12 +665,14 @@ protected function getShippingCosts(array $data, int $calculationType, ?array $r } if (isset($shippingCost['factor']) && $shippingCost['factor'] > 0) { - $this->loggingService->addLogEntry(new UnsupportedShippingPriceLog( - $this->runId, - DefaultEntities::SHIPPING_METHOD_PRICE, - $shippingCost['id'], - $this->oldShippingMethod - )); + $this->loggingService->addLogEntry( + MigrationLogBuilder::fromMigrationContext($migrationContext) + ->withEntityName(ShippingMethodPriceDefinition::ENTITY_NAME) + ->withFieldSourcePath('factor') + ->withSourceData($shippingCost) + ->withConvertedData($cost) + ->build(UnsupportedShippingPriceLog::class) + ); continue; } @@ -735,7 +706,7 @@ private function setCustomAvailabilityRule(array $data, array &$converted): void $ruleData = $this->getRelevantDataForAvailabilityRule($data); $jsonRuleData = \json_encode($ruleData, \JSON_THROW_ON_ERROR); - $hash = \md5($jsonRuleData); + $hash = Hasher::hash($jsonRuleData, 'md5'); $mainRuleMapping = $this->mappingService->getOrCreateMapping( $this->connectionId, @@ -746,7 +717,7 @@ private function setCustomAvailabilityRule(array $data, array &$converted): void $this->mappingIds[] = $mainRuleMapping['id']; $mainRule = [ - 'id' => (string) $mainRuleMapping['entityUuid'], + 'id' => (string) $mainRuleMapping['entityId'], 'priority' => 100, 'moduleTypes' => [ 'types' => [ @@ -774,17 +745,18 @@ private function setCustomAvailabilityRule(array $data, array &$converted): void $this->mappingIds[] = $mainAndContainerMapping['id']; $mainOrContainer = [ - 'id' => (string) $mainOrContainerMapping['entityUuid'], - 'ruleId' => (string) $mainRuleMapping['entityUuid'], + 'id' => (string) $mainOrContainerMapping['entityId'], + 'ruleId' => (string) $mainRuleMapping['entityId'], 'type' => 'orContainer', 'position' => 0, 'children' => [ [ - 'id' => (string) $mainAndContainerMapping['entityUuid'], - 'ruleId' => (string) $mainRuleMapping['entityUuid'], - 'parentId' => (string) $mainOrContainerMapping['entityUuid'], + 'id' => (string) $mainAndContainerMapping['entityId'], + 'ruleId' => (string) $mainRuleMapping['entityId'], + 'parentId' => (string) $mainOrContainerMapping['entityId'], 'type' => 'andContainer', 'position' => 0, + 'children' => [], ], ], ]; @@ -809,10 +781,11 @@ private function setCustomAvailabilityRule(array $data, array &$converted): void } /** - * @return array>> + * @return list, children: list>}> */ private function getDayOfWeekChildren(int $from, int $to, string $ruleId, string $parentId): array { + /** @var list, children: list>}> $values */ $values = []; $oldTo = null; if ($from > $to) { @@ -830,7 +803,7 @@ private function getDayOfWeekChildren(int $from, int $to, string $ruleId, string } /** - * @param array $values + * @param list, children: list>}> $values */ private function setDayOfWeekValues(array &$values, int $from, int $to, string $ruleId, string $parentId): void { @@ -844,7 +817,7 @@ private function setDayOfWeekValues(array &$values, int $from, int $to, string $ ); $value = [ - 'id' => $dayMapping['entityUuid'], + 'id' => (string) $dayMapping['entityId'], 'type' => 'dayOfWeek', 'ruleId' => $ruleId, 'parentId' => $parentId, @@ -852,8 +825,10 @@ private function setDayOfWeekValues(array &$values, int $from, int $to, string $ 'operator' => '=', 'dayOfWeek' => $day, ], + 'children' => [], ]; + // @phpstan-ignore-next-line parameterByRef.type $values[] = $value; } } @@ -907,7 +882,7 @@ private function setWeekdayCondition( $this->mappingIds[] = $dayOfWeekOrContainerMapping['id']; $dayOfWeekOrContainer = [ - 'id' => $dayOfWeekOrContainerMapping['entityUuid'], + 'id' => $dayOfWeekOrContainerMapping['entityId'], 'ruleId' => $mainRuleUuid, 'parentId' => $mainAndContainerUuid, 'type' => 'orContainer', @@ -967,12 +942,13 @@ private function setBindTimeCondition( } $condition = [ - 'id' => $conditionMapping['entityUuid'], + 'id' => $conditionMapping['entityId'], 'ruleId' => $mainRuleUuid, 'parentId' => $mainAndContainerUuid, 'position' => ++$position, 'type' => 'timeRange', 'value' => $value, + 'children' => [], ]; $mainOrContainer['children'][0]['children'][] = $condition; @@ -1003,7 +979,7 @@ private function setLastStockCondition( ); $condition = [ - 'id' => $conditionMapping['entityUuid'], + 'id' => $conditionMapping['entityId'], 'ruleId' => $mainRuleUuid, 'parentId' => $mainAndContainerUuid, 'type' => 'cartLineItemClearanceSale', @@ -1011,6 +987,7 @@ private function setLastStockCondition( 'value' => [ 'clearanceSale' => true, ], + 'children' => [], ]; $mainOrContainer['children'][0]['children'][] = $condition; @@ -1049,7 +1026,7 @@ private function setOtherConditions( ); $condition = [ - 'id' => $conditionMapping['entityUuid'], + 'id' => $conditionMapping['entityId'], 'ruleId' => $mainRuleUuid, 'parentId' => $mainAndContainerUuid, 'type' => $conditionValueMapping[$key]['type'], @@ -1058,8 +1035,10 @@ private function setOtherConditions( 'operator' => $conditionValueMapping[$key]['operator'], $conditionValueMapping[$key]['value'] => (float) $data, ], + 'children' => [], ]; + // @phpstan-ignore-next-line parameterByRef.type $mainOrContainer['children'][0]['children'][] = $condition; } } @@ -1098,7 +1077,7 @@ private function setShippingCountries(array &$ruleData, string $hash, int &$posi } $condition = [ - 'id' => $conditionMapping['entityUuid'], + 'id' => $conditionMapping['entityId'], 'ruleId' => $mainRuleUuid, 'parentId' => $mainAndContainerUuid, 'type' => 'customerShippingCountry', @@ -1107,6 +1086,7 @@ private function setShippingCountries(array &$ruleData, string $hash, int &$posi 'operator' => '=', 'countryIds' => $countries, ], + 'children' => [], ]; $mainOrContainer['children'][0]['children'][] = $condition; @@ -1146,7 +1126,7 @@ private function setPaymentMethods(array &$ruleData, string $hash, int &$positio } $this->mappingIds[] = $paymentMethodMapping['id']; - $paymentMethods[] = $paymentMethodMapping['entityUuid']; + $paymentMethods[] = $paymentMethodMapping['entityId']; } if (empty($paymentMethods)) { @@ -1154,7 +1134,7 @@ private function setPaymentMethods(array &$ruleData, string $hash, int &$positio } $condition = [ - 'id' => $conditionMapping['entityUuid'], + 'id' => $conditionMapping['entityId'], 'ruleId' => $mainRuleUuid, 'parentId' => $mainAndContainerUuid, 'type' => 'paymentMethod', @@ -1163,6 +1143,7 @@ private function setPaymentMethods(array &$ruleData, string $hash, int &$positio 'operator' => '=', 'paymentMethodIds' => $paymentMethods, ], + 'children' => [], ]; $mainOrContainer['children'][0]['children'][] = $condition; @@ -1202,7 +1183,7 @@ private function setExcludedCategories(array &$ruleData, string $hash, int &$pos } $this->mappingIds[] = $categoryMapping['id']; - $excludedCategories[] = $categoryMapping['entityUuid']; + $excludedCategories[] = $categoryMapping['entityId']; } if (empty($excludedCategories)) { @@ -1210,7 +1191,7 @@ private function setExcludedCategories(array &$ruleData, string $hash, int &$pos } $condition = [ - 'id' => $conditionMapping['entityUuid'], + 'id' => $conditionMapping['entityId'], 'ruleId' => $mainRuleUuid, 'parentId' => $mainAndContainerUuid, 'type' => 'cartLineItemInCategory', @@ -1219,6 +1200,7 @@ private function setExcludedCategories(array &$ruleData, string $hash, int &$pos 'operator' => '!=', 'categoryIds' => $excludedCategories, ], + 'children' => [], ]; $mainOrContainer['children'][0]['children'][] = $condition; @@ -1249,11 +1231,12 @@ private function setFreeShipping( ); $condition = [ - 'id' => $conditionMapping['entityUuid'], + 'id' => $conditionMapping['entityId'], 'ruleId' => $mainRuleUuid, 'parentId' => $mainAndContainerUuid, 'type' => 'cartHasDeliveryFreeItem', 'position' => ++$position, + 'children' => [], ]; $mainOrContainer['children'][0]['children'][] = $condition; diff --git a/src/Profile/Shopware/Converter/ShopwareConverter.php b/src/Profile/Shopware/Converter/ShopwareConverter.php index e01821c5a..e0549101f 100644 --- a/src/Profile/Shopware/Converter/ShopwareConverter.php +++ b/src/Profile/Shopware/Converter/ShopwareConverter.php @@ -92,24 +92,6 @@ protected function checkForEmptyRequiredDataFields(array $rawData, array $requir return $emptyFields; } - /** - * @param array $converted - * @param array $requiredDataFields - * - * @return list - */ - protected function checkForEmptyRequiredConvertedFields(array $converted, array $requiredDataFields): array - { - $emptyFields = []; - foreach ($requiredDataFields as $requiredDataFieldKey => $requiredDataFieldValue) { - if (!isset($converted[$requiredDataFieldKey]) || $converted[$requiredDataFieldKey] === '') { - $emptyFields[] = $requiredDataFieldValue; - } - } - - return $emptyFields; - } - protected function validDate(string $value): bool { try { @@ -148,7 +130,7 @@ protected function getAttributes( } $connection = $this->migrationContext->getConnection(); - if ($context !== null && $connection !== null) { + if ($context !== null) { $connectionId = $connection->getId(); $mapping = $this->mappingService->getMapping( $connectionId, diff --git a/src/Profile/Shopware/Converter/TranslationConverter.php b/src/Profile/Shopware/Converter/TranslationConverter.php index c0e99804a..9a0ee0ab5 100644 --- a/src/Profile/Shopware/Converter/TranslationConverter.php +++ b/src/Profile/Shopware/Converter/TranslationConverter.php @@ -7,26 +7,33 @@ namespace SwagMigrationAssistant\Profile\Shopware\Converter; +use Shopware\Core\Content\Category\Aggregate\CategoryTranslation\CategoryTranslationDefinition; use Shopware\Core\Content\Category\CategoryDefinition; +use Shopware\Core\Content\Media\Aggregate\MediaTranslation\MediaTranslationDefinition; use Shopware\Core\Content\Media\MediaDefinition; use Shopware\Core\Content\Product\Aggregate\ProductManufacturer\ProductManufacturerDefinition; +use Shopware\Core\Content\Product\Aggregate\ProductManufacturerTranslation\ProductManufacturerTranslationDefinition; +use Shopware\Core\Content\Product\Aggregate\ProductTranslation\ProductTranslationDefinition; use Shopware\Core\Content\Product\ProductDefinition; use Shopware\Core\Content\Property\Aggregate\PropertyGroupOption\PropertyGroupOptionDefinition; +use Shopware\Core\Content\Property\Aggregate\PropertyGroupOptionTranslation\PropertyGroupOptionTranslationDefinition; +use Shopware\Core\Content\Property\Aggregate\PropertyGroupTranslation\PropertyGroupTranslationDefinition; use Shopware\Core\Content\Property\PropertyGroupDefinition; use Shopware\Core\Framework\Context; use Shopware\Core\Framework\Log\Package; +use Shopware\Core\System\Unit\Aggregate\UnitTranslation\UnitTranslationDefinition; use Shopware\Core\System\Unit\UnitDefinition; use SwagMigrationAssistant\Migration\Connection\Helper\ConnectionNameSanitizer; use SwagMigrationAssistant\Migration\Converter\ConvertStruct; use SwagMigrationAssistant\Migration\DataSelection\DefaultEntities; use SwagMigrationAssistant\Migration\Logging\Log\AssociationRequiredMissingLog; -use SwagMigrationAssistant\Migration\Logging\Log\EmptyNecessaryFieldRunLog; -use SwagMigrationAssistant\Migration\Logging\Log\InvalidUnserializedData; +use SwagMigrationAssistant\Migration\Logging\Log\Builder\MigrationLogBuilder; +use SwagMigrationAssistant\Migration\Logging\Log\InvalidUnserializedDataLog; use SwagMigrationAssistant\Migration\Logging\LoggingServiceInterface; use SwagMigrationAssistant\Migration\Mapping\Lookup\LanguageLookup; use SwagMigrationAssistant\Migration\Mapping\MappingServiceInterface; use SwagMigrationAssistant\Migration\MigrationContextInterface; -use SwagMigrationAssistant\Profile\Shopware\Logging\Log\UnsupportedTranslationType; +use SwagMigrationAssistant\Profile\Shopware\Logging\Log\UnsupportedTranslationTypeLog; #[Package('fundamentals@after-sales')] abstract class TranslationConverter extends ShopwareConverter @@ -56,21 +63,7 @@ public function convert( $this->runId = $migrationContext->getRunUuid(); $connection = $migrationContext->getConnection(); - $this->connectionId = ''; - if ($connection !== null) { - $this->connectionId = $connection->getId(); - } - - if (!isset($data['locale'])) { - $this->loggingService->addLogEntry(new EmptyNecessaryFieldRunLog( - $this->runId, - DefaultEntities::TRANSLATION, - $data['id'], - 'locale' - )); - - return new ConvertStruct(null, $data); - } + $this->connectionId = $connection->getId(); switch ($data['objecttype']) { case 'article': @@ -97,12 +90,11 @@ public function convert( } $this->loggingService->addLogEntry( - new UnsupportedTranslationType( - $migrationContext->getRunUuid(), - $data['objecttype'], - DefaultEntities::TRANSLATION, - $data['id'] - ) + MigrationLogBuilder::fromMigrationContext($migrationContext) + ->withEntityName('unknown_translation') + ->withFieldSourcePath('objecttype') + ->withSourceData($data) + ->build(UnsupportedTranslationTypeLog::class) ); return new ConvertStruct(null, $data); @@ -133,17 +125,17 @@ protected function createProductTranslation(array &$data): ConvertStruct if ($mapping === null) { $this->loggingService->addLogEntry( - new AssociationRequiredMissingLog( - $this->runId, - DefaultEntities::PRODUCT, - $data['id'], - DefaultEntities::TRANSLATION - ) + MigrationLogBuilder::fromMigrationContext($this->migrationContext) + ->withEntityName(ProductTranslationDefinition::ENTITY_NAME) + ->withFieldName('productId') + ->withFieldSourcePath('objectkey') + ->withSourceData($sourceData) + ->build(AssociationRequiredMissingLog::class) ); return new ConvertStruct(null, $sourceData); } - $product['id'] = $mapping['entityUuid']; + $product['id'] = $mapping['entityId']; $this->mappingIds[] = $mapping['id']; $product['entityDefinitionClass'] = ProductDefinition::class; @@ -204,13 +196,15 @@ protected function createProductTranslation(array &$data): ConvertStruct $this->context, $this->checksum ); - $productTranslation['id'] = $this->mainMapping['entityUuid']; + $productTranslation['id'] = $this->mainMapping['entityId']; unset($data['id']); - $languageUuid = $this->languageLookup->get($data['locale'], $this->context); - if ($languageUuid !== null) { - $productTranslation['languageId'] = $languageUuid; - $product['translations'][$languageUuid] = $productTranslation; + if (isset($data['locale'])) { + $languageUuid = $this->languageLookup->get($data['locale'], $this->context); + if ($languageUuid !== null) { + $productTranslation['languageId'] = $languageUuid; + $product['translations'][$languageUuid] = $productTranslation; + } } unset($data['name'], $data['locale']); @@ -244,17 +238,17 @@ protected function createProductVariantTranslation(array &$data): ConvertStruct if ($mapping === null) { $this->loggingService->addLogEntry( - new AssociationRequiredMissingLog( - $this->runId, - DefaultEntities::PRODUCT, - $data['id'], - DefaultEntities::TRANSLATION - ) + MigrationLogBuilder::fromMigrationContext($this->migrationContext) + ->withEntityName(ProductTranslationDefinition::ENTITY_NAME) + ->withFieldName('productId') + ->withFieldSourcePath('ordernumber') + ->withSourceData($sourceData) + ->build(AssociationRequiredMissingLog::class) ); return new ConvertStruct(null, $sourceData); } - $product['id'] = $mapping['entityUuid']; + $product['id'] = $mapping['entityId']; $this->mappingIds[] = $mapping['id']; $product['entityDefinitionClass'] = ProductDefinition::class; @@ -283,7 +277,7 @@ protected function createProductVariantTranslation(array &$data): ConvertStruct $this->context, $this->checksum ); - $productTranslation['id'] = $this->mainMapping['entityUuid']; + $productTranslation['id'] = $this->mainMapping['entityId']; unset($data['id']); $languageUuid = $this->languageLookup->get($data['locale'], $this->context); @@ -320,17 +314,17 @@ protected function createManufacturerProductTranslation(array $data): ConvertStr if ($mapping === null) { $this->loggingService->addLogEntry( - new AssociationRequiredMissingLog( - $this->runId, - DefaultEntities::PRODUCT_MANUFACTURER, - $data['id'], - DefaultEntities::TRANSLATION - ) + MigrationLogBuilder::fromMigrationContext($this->migrationContext) + ->withEntityName(ProductManufacturerTranslationDefinition::ENTITY_NAME) + ->withFieldName('productManufacturerId') + ->withFieldSourcePath('objectkey') + ->withSourceData($sourceData) + ->build(AssociationRequiredMissingLog::class) ); return new ConvertStruct(null, $sourceData); } - $manufacturer['id'] = $mapping['entityUuid']; + $manufacturer['id'] = $mapping['entityId']; $this->mappingIds[] = $mapping['id']; $manufacturer['entityDefinitionClass'] = ProductManufacturerDefinition::class; @@ -347,7 +341,7 @@ protected function createManufacturerProductTranslation(array $data): ConvertStr $this->context, $this->checksum ); - $manufacturerTranslation['id'] = $this->mainMapping['entityUuid']; + $manufacturerTranslation['id'] = $this->mainMapping['entityId']; unset($data['id'], $data['objectkey']); $this->convertValue($manufacturerTranslation, 'name', $data, 'name'); @@ -402,17 +396,17 @@ protected function createUnitTranslation(array $data): ConvertStruct if ($mapping === null) { $this->loggingService->addLogEntry( - new AssociationRequiredMissingLog( - $this->runId, - DefaultEntities::UNIT, - $data['id'], - DefaultEntities::TRANSLATION - ) + MigrationLogBuilder::fromMigrationContext($this->migrationContext) + ->withEntityName(UnitTranslationDefinition::ENTITY_NAME) + ->withFieldName('unitId') + ->withFieldSourcePath('objectkey') + ->withSourceData($sourceData) + ->build(AssociationRequiredMissingLog::class) ); return new ConvertStruct(null, $sourceData); } - $unit['id'] = $mapping['entityUuid']; + $unit['id'] = $mapping['entityId']; $this->mappingIds[] = $mapping['id']; $unit['entityDefinitionClass'] = UnitDefinition::class; @@ -429,7 +423,7 @@ protected function createUnitTranslation(array $data): ConvertStruct $this->context, $this->checksum ); - $unitTranslation['id'] = $this->mainMapping['entityUuid']; + $unitTranslation['id'] = $this->mainMapping['entityId']; $objectData = \array_pop($objectData); @@ -489,17 +483,17 @@ protected function createCategoryTranslation(array $data): ConvertStruct if ($mapping === null) { $this->loggingService->addLogEntry( - new AssociationRequiredMissingLog( - $this->runId, - DefaultEntities::CATEGORY, - $data['id'], - DefaultEntities::TRANSLATION - ) + MigrationLogBuilder::fromMigrationContext($this->migrationContext) + ->withEntityName(CategoryTranslationDefinition::ENTITY_NAME) + ->withFieldName('categoryId') + ->withFieldSourcePath('objectkey') + ->withSourceData($sourceData) + ->build(AssociationRequiredMissingLog::class) ); return new ConvertStruct(null, $sourceData); } - $category['id'] = $mapping['entityUuid']; + $category['id'] = $mapping['entityId']; $this->mappingIds[] = $mapping['id']; $category['entityDefinitionClass'] = CategoryDefinition::class; @@ -523,7 +517,7 @@ protected function createCategoryTranslation(array $data): ConvertStruct $this->context, $this->checksum ); - $categoryTranslation['id'] = $this->mainMapping['entityUuid']; + $categoryTranslation['id'] = $this->mainMapping['entityId']; $this->convertValue($categoryTranslation, 'name', $objectData, 'description'); $this->convertValue($categoryTranslation, 'description', $objectData, 'cmstext'); @@ -586,17 +580,17 @@ protected function createConfiguratorOptionTranslation(array $data): ConvertStru if ($mapping === null) { $this->loggingService->addLogEntry( - new AssociationRequiredMissingLog( - $this->runId, - DefaultEntities::PROPERTY_GROUP_OPTION, - $data['id'], - DefaultEntities::TRANSLATION - ) + MigrationLogBuilder::fromMigrationContext($this->migrationContext) + ->withEntityName(PropertyGroupOptionTranslationDefinition::ENTITY_NAME) + ->withFieldName('propertyGroupOptionId') + ->withFieldSourcePath('objectkey') + ->withSourceData($sourceData) + ->build(AssociationRequiredMissingLog::class) ); return new ConvertStruct(null, $sourceData); } - $configuratorOption['id'] = $mapping['entityUuid']; + $configuratorOption['id'] = $mapping['entityId']; $this->mappingIds[] = $mapping['id']; $configuratorOption['entityDefinitionClass'] = PropertyGroupOptionDefinition::class; @@ -612,7 +606,7 @@ protected function createConfiguratorOptionTranslation(array $data): ConvertStru $data['id'], $this->context ); - $propertyGroupOptionTranslation['id'] = $this->mainMapping['entityUuid']; + $propertyGroupOptionTranslation['id'] = $this->mainMapping['entityId']; foreach ($objectData as $key => $value) { if ($key === 'name') { @@ -665,17 +659,17 @@ protected function createConfiguratorOptionGroupTranslation(array $data): Conver if ($mapping === null) { $this->loggingService->addLogEntry( - new AssociationRequiredMissingLog( - $this->runId, - DefaultEntities::PROPERTY_GROUP, - $data['id'], - DefaultEntities::TRANSLATION - ) + MigrationLogBuilder::fromMigrationContext($this->migrationContext) + ->withEntityName(PropertyGroupTranslationDefinition::ENTITY_NAME) + ->withFieldName('propertyGroupId') + ->withFieldSourcePath('objectkey') + ->withSourceData($sourceData) + ->build(AssociationRequiredMissingLog::class) ); return new ConvertStruct(null, $sourceData); } - $configuratorOptionGroup['id'] = $mapping['entityUuid']; + $configuratorOptionGroup['id'] = $mapping['entityId']; $this->mappingIds[] = $mapping['id']; $configuratorOptionGroup['entityDefinitionClass'] = PropertyGroupDefinition::class; @@ -692,7 +686,7 @@ protected function createConfiguratorOptionGroupTranslation(array $data): Conver $this->context, $this->checksum ); - $propertyGroupTranslation['id'] = $this->mainMapping['entityUuid']; + $propertyGroupTranslation['id'] = $this->mainMapping['entityId']; foreach ($objectData as $key => $value) { if ($key === 'name') { @@ -747,17 +741,17 @@ protected function createPropertyValueTranslation(array $data): ConvertStruct if ($mapping === null) { $this->loggingService->addLogEntry( - new AssociationRequiredMissingLog( - $this->runId, - DefaultEntities::PROPERTY_GROUP_OPTION, - $data['id'], - DefaultEntities::TRANSLATION - ) + MigrationLogBuilder::fromMigrationContext($this->migrationContext) + ->withEntityName(PropertyGroupOptionTranslationDefinition::ENTITY_NAME) + ->withFieldName('propertyGroupOptionId') + ->withFieldSourcePath('objectkey') + ->withSourceData($sourceData) + ->build(AssociationRequiredMissingLog::class) ); return new ConvertStruct(null, $sourceData); } - $propertyValue['id'] = $mapping['entityUuid']; + $propertyValue['id'] = $mapping['entityId']; $this->mappingIds[] = $mapping['id']; $propertyValue['entityDefinitionClass'] = PropertyGroupOptionDefinition::class; @@ -773,7 +767,7 @@ protected function createPropertyValueTranslation(array $data): ConvertStruct $data['id'], $this->context ); - $propertyValueTranslation['id'] = $this->mainMapping['entityUuid']; + $propertyValueTranslation['id'] = $this->mainMapping['entityId']; foreach ($objectData as $key => $value) { if ($key === 'optionValue') { @@ -824,17 +818,17 @@ protected function createPropertyOptionTranslation(array $data): ConvertStruct if ($mapping === null) { $this->loggingService->addLogEntry( - new AssociationRequiredMissingLog( - $this->runId, - DefaultEntities::PROPERTY_GROUP, - $data['id'], - DefaultEntities::TRANSLATION - ) + MigrationLogBuilder::fromMigrationContext($this->migrationContext) + ->withEntityName(PropertyGroupTranslationDefinition::ENTITY_NAME) + ->withFieldName('propertyGroupId') + ->withFieldSourcePath('objectkey') + ->withSourceData($sourceData) + ->build(AssociationRequiredMissingLog::class) ); return new ConvertStruct(null, $sourceData); } - $propertyOption['id'] = $mapping['entityUuid']; + $propertyOption['id'] = $mapping['entityId']; $this->mappingIds[] = $mapping['id']; $propertyOption['entityDefinitionClass'] = PropertyGroupDefinition::class; @@ -851,7 +845,7 @@ protected function createPropertyOptionTranslation(array $data): ConvertStruct $this->context, $this->checksum ); - $propertyOptionTranslation['id'] = $this->mainMapping['entityUuid']; + $propertyOptionTranslation['id'] = $this->mainMapping['entityId']; foreach ($objectData as $key => $value) { if ($key === 'optionName') { @@ -891,12 +885,11 @@ protected function createPropertyOptionTranslation(array $data): ConvertStruct */ protected function addAttribute(string $entityName, string $key, string $value, array &$translation, array &$objectData): void { - $connection = $this->migrationContext->getConnection(); - - if ($connection === null || $value === '') { + if ($value === '') { return; } + $connection = $this->migrationContext->getConnection(); $connectionName = ConnectionNameSanitizer::sanitize($connection->getName()); $isAttribute = \mb_strpos($key, '__attribute_'); @@ -947,22 +940,24 @@ protected function addAttribute(string $entityName, string $key, string $value, protected function unserializeTranslation(array $data, string $entity): ?array { $objectDataSerialized = $data['objectdata']; + $exception = null; try { $objectData = \unserialize($objectDataSerialized, ['allowed_classes' => false]); - } catch (\Throwable $error) { + } catch (\Throwable $e) { $objectData = null; + $exception = $e; } if (!\is_array($objectData)) { $this->loggingService->addLogEntry( - new InvalidUnserializedData( - $this->runId, - DefaultEntities::TRANSLATION, - $data['id'], - $entity, - $objectDataSerialized - ) + MigrationLogBuilder::fromMigrationContext($this->migrationContext) + ->withEntityName($entity) + ->withFieldSourcePath('objectdata') + ->withSourceData($data) + ->withExceptionMessage($exception?->getMessage() ?? 'Unserialization failed') + ->withExceptionTrace($exception?->getTrace() ?? []) + ->build(InvalidUnserializedDataLog::class) ); return null; @@ -991,19 +986,19 @@ protected function createProductMediaTranslation(array $data): ConvertStruct if ($mapping === null) { $this->loggingService->addLogEntry( - new AssociationRequiredMissingLog( - $this->runId, - DefaultEntities::MEDIA, - $data['mediaId'], - DefaultEntities::TRANSLATION - ) + MigrationLogBuilder::fromMigrationContext($this->migrationContext) + ->withEntityName(MediaTranslationDefinition::ENTITY_NAME) + ->withFieldName('mediaId') + ->withFieldSourcePath('mediaId') + ->withSourceData($sourceData) + ->build(AssociationRequiredMissingLog::class) ); return new ConvertStruct(null, $sourceData); } unset($data['objectkey'], $data['mediaId']); - $media['id'] = $mapping['entityUuid']; + $media['id'] = $mapping['entityId']; $this->mappingIds[] = $mapping['id']; $media['entityDefinitionClass'] = MediaDefinition::class; @@ -1020,7 +1015,7 @@ protected function createProductMediaTranslation(array $data): ConvertStruct $this->context, $this->checksum ); - $mediaTranslation['id'] = $this->mainMapping['entityUuid']; + $mediaTranslation['id'] = $this->mainMapping['entityId']; foreach (\array_keys($objectData) as $key) { if ($key === 'description') { diff --git a/src/Profile/Shopware/Gateway/Api/Reader/EnvironmentReader.php b/src/Profile/Shopware/Gateway/Api/Reader/EnvironmentReader.php index 0e9042dcb..5c9382b9d 100644 --- a/src/Profile/Shopware/Gateway/Api/Reader/EnvironmentReader.php +++ b/src/Profile/Shopware/Gateway/Api/Reader/EnvironmentReader.php @@ -116,7 +116,7 @@ private function doRequest(string $endpoint): ResponseInterface return $this->client->get($endpoint); } catch (ClientException $e) { if ($e->getCode() === SymfonyResponse::HTTP_UNAUTHORIZED) { - throw MigrationException::invalidConnectionAuthentication($endpoint); + throw MigrationException::invalidConnectionCredentials($endpoint); } throw $e; diff --git a/src/Profile/Shopware/Gateway/Api/Reader/TableCountReader.php b/src/Profile/Shopware/Gateway/Api/Reader/TableCountReader.php index 91af0c900..0d2fcaf0c 100644 --- a/src/Profile/Shopware/Gateway/Api/Reader/TableCountReader.php +++ b/src/Profile/Shopware/Gateway/Api/Reader/TableCountReader.php @@ -10,6 +10,7 @@ use Shopware\Core\Framework\Context; use Shopware\Core\Framework\Log\Package; use SwagMigrationAssistant\Exception\MigrationException; +use SwagMigrationAssistant\Migration\Logging\Log\Builder\MigrationLogBuilder; use SwagMigrationAssistant\Migration\Logging\Log\CannotReadEntityCountLog; use SwagMigrationAssistant\Migration\Logging\LoggingService; use SwagMigrationAssistant\Migration\MigrationContextInterface; @@ -68,14 +69,11 @@ private function prepareTotals(array $result): array private function logExceptions(array $exceptionArray, MigrationContextInterface $migrationContext, Context $context): void { foreach ($exceptionArray as $exception) { - $this->loggingService->addLogEntry(new CannotReadEntityCountLog( - $migrationContext->getRunUuid(), - $exception['entity'], - $exception['table'], - $exception['condition'], - $exception['code'], - $exception['message'] - )); + $this->loggingService->addLogEntry( + MigrationLogBuilder::fromMigrationContext($migrationContext) + ->withExceptionMessage($exception['message']) + ->build(CannotReadEntityCountLog::class) + ); } $this->loggingService->saveLogging($context); diff --git a/src/Profile/Shopware/Gateway/Api/ShopwareApiGateway.php b/src/Profile/Shopware/Gateway/Api/ShopwareApiGateway.php index 5c93752bb..3924b3074 100644 --- a/src/Profile/Shopware/Gateway/Api/ShopwareApiGateway.php +++ b/src/Profile/Shopware/Gateway/Api/ShopwareApiGateway.php @@ -12,6 +12,7 @@ use Shopware\Core\Framework\DataAbstractionLayer\EntityRepository; use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria; use Shopware\Core\Framework\Log\Package; +use Shopware\Core\Framework\Util\Hasher; use Shopware\Core\System\Currency\CurrencyCollection; use Shopware\Core\System\Currency\CurrencyEntity; use Shopware\Core\System\Language\LanguageCollection; @@ -22,6 +23,7 @@ use SwagMigrationAssistant\Migration\Gateway\Reader\EnvironmentReaderInterface; use SwagMigrationAssistant\Migration\Gateway\Reader\ReaderRegistryInterface; use SwagMigrationAssistant\Migration\MigrationContextInterface; +use SwagMigrationAssistant\Migration\Profile\ProfileInterface; use SwagMigrationAssistant\Profile\Shopware\Gateway\ShopwareGatewayInterface; use SwagMigrationAssistant\Profile\Shopware\Gateway\TableCountReaderInterface; use SwagMigrationAssistant\Profile\Shopware\Gateway\TableReaderInterface; @@ -56,9 +58,9 @@ public function getSnippetName(): string return 'swag-migration.wizard.pages.connectionCreate.gateways.shopwareApi'; } - public function supports(MigrationContextInterface $migrationContext): bool + public function supports(ProfileInterface $profile): bool { - return $migrationContext->getProfile() instanceof ShopwareProfileInterface; + return $profile instanceof ShopwareProfileInterface; } public function read(MigrationContextInterface $migrationContext): array @@ -124,21 +126,7 @@ public function readEnvironmentInformation(MigrationContextInterface $migrationC $environmentDataArray['defaultShopLanguage'] = \str_replace('_', '-', $environmentDataArray['defaultShopLanguage']); $totals = $this->readTotals($migrationContext, $context); - - $connection = $migrationContext->getConnection(); - - if ($connection === null) { - return new EnvironmentInformation( - $profile->getSourceSystemName(), - $profile->getVersion(), - '', - [], - [], - null - ); - } - - $credentials = $connection->getCredentialFields(); + $credentials = $migrationContext->getConnection()->getCredentialFields(); if ($credentials === null) { return new EnvironmentInformation( @@ -171,10 +159,29 @@ public function readEnvironmentInformation(MigrationContextInterface $migrationC $targetCurrencyIsoCode, $environmentDataArray['defaultCurrency'], $environmentDataArray['defaultShopLanguage'], - $targetLocaleCode + $targetLocaleCode, + $this->generateFingerprint($environmentDataArray), ); } + /** + * @param array $environmentData + */ + private function generateFingerprint(array $environmentData): ?string + { + if (!isset($environmentData['config'])) { + return null; + } + + $config = $environmentData['config']; + + if (!isset($config['esdKey'], $config['installationDate'])) { + return null; + } + + return Hasher::hash($config['esdKey'] . $config['installationDate']); + } + public function readTotals(MigrationContextInterface $migrationContext, Context $context): array { return $this->tableCountReader->readTotals($migrationContext, $context); diff --git a/src/Profile/Shopware/Gateway/Connection/ConnectionFactory.php b/src/Profile/Shopware/Gateway/Connection/ConnectionFactory.php index fa949b6a9..bf9792d2f 100644 --- a/src/Profile/Shopware/Gateway/Connection/ConnectionFactory.php +++ b/src/Profile/Shopware/Gateway/Connection/ConnectionFactory.php @@ -24,13 +24,7 @@ class ConnectionFactory implements ConnectionFactoryInterface, ResetInterface public function createApiClient(MigrationContextInterface $migrationContext): HttpClientInterface { - $connection = $migrationContext->getConnection(); - - if ($connection === null) { - throw MigrationException::noConnectionFound(); - } - - $credentials = $connection->getCredentialFields(); + $credentials = $migrationContext->getConnection()->getCredentialFields(); if (empty($credentials)) { throw MigrationException::invalidConnectionCredentials(); @@ -57,13 +51,7 @@ public function createDatabaseConnection(MigrationContextInterface $migrationCon return $this->externalConnection; } - $connection = $migrationContext->getConnection(); - - if ($connection === null) { - throw MigrationException::noConnectionFound(); - } - - $credentials = $connection->getCredentialFields(); + $credentials = $migrationContext->getConnection()->getCredentialFields(); if ($credentials === null) { throw MigrationException::invalidConnectionCredentials(); diff --git a/src/Profile/Shopware/Gateway/Local/Reader/AttributeReader.php b/src/Profile/Shopware/Gateway/Local/Reader/AttributeReader.php index cd693effe..6556dcdee 100644 --- a/src/Profile/Shopware/Gateway/Local/Reader/AttributeReader.php +++ b/src/Profile/Shopware/Gateway/Local/Reader/AttributeReader.php @@ -105,7 +105,9 @@ private function getAttributeConfiguration(string $table, MigrationContextInterf ->setParameter('table', $table); /** @var array> $attributeConfiguration */ - $attributeConfiguration = FetchModeHelper::groupUnique($query->executeQuery()->fetchAllAssociative()); + $attributeConfiguration = FetchModeHelper::groupUnique( + $query->executeQuery()->fetchAllAssociative() + ); $sql = << $this->getHost($migrationContext), 'additionalData' => $this->getAdditionalData($migrationContext), 'defaultCurrency' => $this->getDefaultCurrency($migrationContext), + 'config' => $this->getConfig($migrationContext), ]; } + /** + * @return array + */ + protected function getConfig(MigrationContextInterface $migrationContext): array + { + $connection = $this->getConnection($migrationContext); + + $configNames = [ + 'esdKey', + 'installationDate', + ]; + + $query = $connection->createQueryBuilder(); + + $query->select('config.name', 'config.value') + ->from('s_core_config_elements', 'config') + ->where('config.name IN (:configNames)') + ->setParameter('configNames', $configNames, ArrayParameterType::STRING); + + $rows = $query->executeQuery()->fetchAllAssociative(); + + $result = []; + + foreach ($rows as $row) { + $result[$row['name']] = \unserialize($row['value'], ['allowed_classes' => false]); + } + + return $result; + } + protected function getDefaultCurrency(MigrationContextInterface $migrationContext): string { $connection = $this->getConnection($migrationContext); diff --git a/src/Profile/Shopware/Gateway/Local/ShopwareLocalGateway.php b/src/Profile/Shopware/Gateway/Local/ShopwareLocalGateway.php index 74ca7e151..e61f24542 100644 --- a/src/Profile/Shopware/Gateway/Local/ShopwareLocalGateway.php +++ b/src/Profile/Shopware/Gateway/Local/ShopwareLocalGateway.php @@ -12,6 +12,7 @@ use Shopware\Core\Framework\DataAbstractionLayer\EntityRepository; use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria; use Shopware\Core\Framework\Log\Package; +use Shopware\Core\Framework\Util\Hasher; use Shopware\Core\System\Currency\CurrencyCollection; use Shopware\Core\System\Currency\CurrencyEntity; use Shopware\Core\System\Language\LanguageCollection; @@ -22,6 +23,7 @@ use SwagMigrationAssistant\Migration\Gateway\Reader\EnvironmentReaderInterface; use SwagMigrationAssistant\Migration\Gateway\Reader\ReaderRegistry; use SwagMigrationAssistant\Migration\MigrationContextInterface; +use SwagMigrationAssistant\Migration\Profile\ProfileInterface; use SwagMigrationAssistant\Migration\RequestStatusStruct; use SwagMigrationAssistant\Profile\Shopware\Gateway\Connection\ConnectionFactoryInterface; use SwagMigrationAssistant\Profile\Shopware\Gateway\ShopwareGatewayInterface; @@ -57,9 +59,9 @@ public function getSnippetName(): string return 'swag-migration.wizard.pages.connectionCreate.gateways.shopwareLocal'; } - public function supports(MigrationContextInterface $migrationContext): bool + public function supports(ProfileInterface $profile): bool { - return $migrationContext->getProfile() instanceof ShopwareProfileInterface; + return $profile instanceof ShopwareProfileInterface; } public function read(MigrationContextInterface $migrationContext): array @@ -75,8 +77,17 @@ public function readEnvironmentInformation(MigrationContextInterface $migrationC try { $connection = $this->connectionFactory->createDatabaseConnection($migrationContext); $connection->executeQuery('SELECT 1'); - } catch (\Throwable $e) { - $error = MigrationException::databaseConnectionError(); + } catch (\Throwable $exception) { + $response = new RequestStatusStruct( + '', + $exception->getMessage(), + false, + $exception + ); + + if ($exception instanceof MigrationException) { + $response->setCode($exception->getErrorCode()); + } return new EnvironmentInformation( $profile->getSourceSystemName(), @@ -84,7 +95,7 @@ public function readEnvironmentInformation(MigrationContextInterface $migrationC '-', [], [], - new RequestStatusStruct($error->getErrorCode(), $error->getMessage()) + $response, ); } @@ -133,10 +144,29 @@ public function readEnvironmentInformation(MigrationContextInterface $migrationC $targetCurrencyIsoCode, $environmentData['defaultCurrency'], $environmentData['defaultShopLanguage'], - $targetLocaleCode + $targetLocaleCode, + $this->generateFingerprint($environmentData) ); } + /** + * @param array $environmentData + */ + private function generateFingerprint(array $environmentData): ?string + { + if (!isset($environmentData['config'])) { + return null; + } + + $config = $environmentData['config']; + + if (!isset($config['esdKey'], $config['installationDate'])) { + return null; + } + + return Hasher::hash($config['esdKey'] . $config['installationDate']); + } + public function readTotals(MigrationContextInterface $migrationContext, Context $context): array { $readers = $this->readerRegistry->getReaderForTotal($migrationContext); diff --git a/src/Profile/Shopware/Logging/Log/DeactivatedPackLanguageLog.php b/src/Profile/Shopware/Logging/Log/DeactivatedPackLanguageLog.php index 956552f0e..99591aa06 100644 --- a/src/Profile/Shopware/Logging/Log/DeactivatedPackLanguageLog.php +++ b/src/Profile/Shopware/Logging/Log/DeactivatedPackLanguageLog.php @@ -8,18 +8,14 @@ namespace SwagMigrationAssistant\Profile\Shopware\Logging\Log; use Shopware\Core\Framework\Log\Package; -use SwagMigrationAssistant\Migration\Logging\Log\BaseRunLogEntry; +use SwagMigrationAssistant\Migration\Logging\Log\Builder\AbstractMigrationLogEntry; #[Package('fundamentals@after-sales')] -class DeactivatedPackLanguageLog extends BaseRunLogEntry +readonly class DeactivatedPackLanguageLog extends AbstractMigrationLogEntry { - public function __construct( - string $runId, - string $entity, - string $sourceId, - private readonly string $languageId, - ) { - parent::__construct($runId, $entity, $sourceId); + public function isUserFixable(): bool + { + return false; } public function getLevel(): string @@ -31,33 +27,4 @@ public function getCode(): string { return 'SWAG_MIGRATION__DEACTIVATED_PACK_LANGUAGE'; } - - public function getTitle(): string - { - return 'Deactivated pack language'; - } - - /** - * @return array{entity: ?string, sourceId: ?string, packLanguage: string} - */ - public function getParameters(): array - { - return [ - 'entity' => $this->getEntity(), - 'sourceId' => $this->getSourceId(), - 'packLanguage' => $this->languageId, - ]; - } - - public function getDescription(): string - { - $args = $this->getParameters(); - - return \sprintf( - 'Language for %s with source id "%s" has been set to default language. The language with id "%s" is not activated for sales channels by "Language pack" plugin.', - $args['entity'], - $args['sourceId'], - $args['packLanguage'] - ); - } } diff --git a/src/Profile/Shopware/Logging/Log/InvalidEmailAddressLog.php b/src/Profile/Shopware/Logging/Log/InvalidEmailAddressLog.php index 23be78316..f35bda3ee 100644 --- a/src/Profile/Shopware/Logging/Log/InvalidEmailAddressLog.php +++ b/src/Profile/Shopware/Logging/Log/InvalidEmailAddressLog.php @@ -8,18 +8,14 @@ namespace SwagMigrationAssistant\Profile\Shopware\Logging\Log; use Shopware\Core\Framework\Log\Package; -use SwagMigrationAssistant\Migration\Logging\Log\BaseRunLogEntry; +use SwagMigrationAssistant\Migration\Logging\Log\Builder\AbstractMigrationLogEntry; #[Package('fundamentals@after-sales')] -class InvalidEmailAddressLog extends BaseRunLogEntry +readonly class InvalidEmailAddressLog extends AbstractMigrationLogEntry { - public function __construct( - string $runId, - string $entity, - string $sourceId, - private readonly string $email, - ) { - parent::__construct($runId, $entity, $sourceId); + public function isUserFixable(): bool + { + return false; } public function getLevel(): string @@ -31,33 +27,4 @@ public function getCode(): string { return 'SWAG_MIGRATION__INVALID_EMAIL_ADDRESS'; } - - public function getTitle(): string - { - return 'Invalid Email address'; - } - - /** - * @return array{entity: ?string, sourceId: ?string, email: string} - */ - public function getParameters(): array - { - return [ - 'entity' => $this->getEntity(), - 'sourceId' => $this->getSourceId(), - 'email' => $this->email, - ]; - } - - public function getDescription(): string - { - $args = $this->getParameters(); - - return \sprintf( - '%s with source id "%s" could not be converted because of invalid email address: %s.', - $args['entity'], - $args['sourceId'], - $args['email'] - ); - } } diff --git a/src/Profile/Shopware/Logging/Log/UnsupportedMailTemplateType.php b/src/Profile/Shopware/Logging/Log/UnsupportedMailTemplateType.php deleted file mode 100644 index 97db7f0e1..000000000 --- a/src/Profile/Shopware/Logging/Log/UnsupportedMailTemplateType.php +++ /dev/null @@ -1,60 +0,0 @@ - - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace SwagMigrationAssistant\Profile\Shopware\Logging\Log; - -use Shopware\Core\Framework\Log\Package; -use SwagMigrationAssistant\Migration\Logging\Log\BaseRunLogEntry; - -#[Package('fundamentals@after-sales')] -class UnsupportedMailTemplateType extends BaseRunLogEntry -{ - public function __construct( - string $runId, - string $sourceId, - private readonly string $type, - ) { - parent::__construct($runId, null, $sourceId); - } - - public function getLevel(): string - { - return self::LOG_LEVEL_INFO; - } - - public function getCode(): string - { - return 'SWAG_MIGRATION__SHOPWARE_UNSUPPORTED_MAIL_TEMPLATE_TYPE'; - } - - public function getTitle(): string - { - return 'Unsupported mail type'; - } - - /** - * @return array{sourceId: ?string, type: string} - */ - public function getParameters(): array - { - return [ - 'sourceId' => $this->getSourceId(), - 'type' => $this->type, - ]; - } - - public function getDescription(): string - { - $args = $this->getParameters(); - - return \sprintf( - 'MailTemplate-Entity with source id "%s" could not be converted because of unsupported type: %s.', - $args['sourceId'], - $args['type'] - ); - } -} diff --git a/src/Profile/Shopware/Logging/Log/UnsupportedMailTemplateTypeLog.php b/src/Profile/Shopware/Logging/Log/UnsupportedMailTemplateTypeLog.php new file mode 100644 index 000000000..5bf8d8127 --- /dev/null +++ b/src/Profile/Shopware/Logging/Log/UnsupportedMailTemplateTypeLog.php @@ -0,0 +1,30 @@ + + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace SwagMigrationAssistant\Profile\Shopware\Logging\Log; + +use Shopware\Core\Framework\Log\Package; +use SwagMigrationAssistant\Migration\Logging\Log\Builder\AbstractMigrationLogEntry; + +#[Package('fundamentals@after-sales')] +readonly class UnsupportedMailTemplateTypeLog extends AbstractMigrationLogEntry +{ + public function isUserFixable(): bool + { + return false; + } + + public function getLevel(): string + { + return self::LOG_LEVEL_INFO; + } + + public function getCode(): string + { + return 'SWAG_MIGRATION__SHOPWARE_UNSUPPORTED_MAIL_TEMPLATE_TYPE'; + } +} diff --git a/src/Profile/Shopware/Logging/Log/UnsupportedNumberRangeTypeLog.php b/src/Profile/Shopware/Logging/Log/UnsupportedNumberRangeTypeLog.php index 7f27e57ee..f7ca603a6 100644 --- a/src/Profile/Shopware/Logging/Log/UnsupportedNumberRangeTypeLog.php +++ b/src/Profile/Shopware/Logging/Log/UnsupportedNumberRangeTypeLog.php @@ -8,18 +8,14 @@ namespace SwagMigrationAssistant\Profile\Shopware\Logging\Log; use Shopware\Core\Framework\Log\Package; -use SwagMigrationAssistant\Migration\Logging\Log\BaseRunLogEntry; +use SwagMigrationAssistant\Migration\Logging\Log\Builder\AbstractMigrationLogEntry; #[Package('fundamentals@after-sales')] -class UnsupportedNumberRangeTypeLog extends BaseRunLogEntry +readonly class UnsupportedNumberRangeTypeLog extends AbstractMigrationLogEntry { - public function __construct( - string $runId, - string $entity, - string $sourceId, - private readonly string $type, - ) { - parent::__construct($runId, $entity, $sourceId); + public function isUserFixable(): bool + { + return false; } public function getLevel(): string @@ -31,32 +27,4 @@ public function getCode(): string { return 'SWAG_MIGRATION__SHOPWARE_UNSUPPORTED_NUMBER_RANGE_TYPE'; } - - public function getTitle(): string - { - return 'Unsupported number range type'; - } - - /** - * @return array{entity: ?string, sourceId: ?string, type: string} - */ - public function getParameters(): array - { - return [ - 'entity' => $this->getEntity(), - 'sourceId' => $this->getSourceId(), - 'type' => $this->type, - ]; - } - - public function getDescription(): string - { - $args = $this->getParameters(); - - return \sprintf( - 'NumberRange-Entity with source id "%s" could not be converted because of unsupported type: %s.', - $args['sourceId'], - $args['type'] - ); - } } diff --git a/src/Profile/Shopware/Logging/Log/UnsupportedSeoUrlType.php b/src/Profile/Shopware/Logging/Log/UnsupportedSeoUrlTypeLog.php similarity index 85% rename from src/Profile/Shopware/Logging/Log/UnsupportedSeoUrlType.php rename to src/Profile/Shopware/Logging/Log/UnsupportedSeoUrlTypeLog.php index 2ed91dbee..adc268f1d 100644 --- a/src/Profile/Shopware/Logging/Log/UnsupportedSeoUrlType.php +++ b/src/Profile/Shopware/Logging/Log/UnsupportedSeoUrlTypeLog.php @@ -8,10 +8,10 @@ namespace SwagMigrationAssistant\Profile\Shopware\Logging\Log; use Shopware\Core\Framework\Log\Package; -use SwagMigrationAssistant\Migration\Logging\Log\UnsupportedObjectType; +use SwagMigrationAssistant\Migration\Logging\Log\UnsupportedObjectTypeLog; #[Package('fundamentals@after-sales')] -class UnsupportedSeoUrlType extends UnsupportedObjectType +readonly class UnsupportedSeoUrlTypeLog extends UnsupportedObjectTypeLog { public function getLevel(): string { diff --git a/src/Profile/Shopware/Logging/Log/UnsupportedShippingCalculationType.php b/src/Profile/Shopware/Logging/Log/UnsupportedShippingCalculationType.php deleted file mode 100644 index 8eaf9fc06..000000000 --- a/src/Profile/Shopware/Logging/Log/UnsupportedShippingCalculationType.php +++ /dev/null @@ -1,62 +0,0 @@ - - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace SwagMigrationAssistant\Profile\Shopware\Logging\Log; - -use Shopware\Core\Framework\Log\Package; -use SwagMigrationAssistant\Migration\Logging\Log\BaseRunLogEntry; - -#[Package('fundamentals@after-sales')] -class UnsupportedShippingCalculationType extends BaseRunLogEntry -{ - public function __construct( - string $runId, - string $entity, - string $sourceId, - private readonly string $type, - ) { - parent::__construct($runId, $entity, $sourceId); - } - - public function getLevel(): string - { - return self::LOG_LEVEL_WARNING; - } - - public function getCode(): string - { - return 'SWAG_MIGRATION__SHOPWARE_UNSUPPORTED_SHIPPING_CALCULATION_TYPE'; - } - - public function getTitle(): string - { - return 'Unsupported shipping calculation type'; - } - - /** - * @return array{entity: ?string, sourceId: ?string, type: string} - */ - public function getParameters(): array - { - return [ - 'entity' => $this->getEntity(), - 'sourceId' => $this->getSourceId(), - 'type' => $this->type, - ]; - } - - public function getDescription(): string - { - $args = $this->getParameters(); - - return \sprintf( - 'ShippingMethod-Entity with source id "%s" could not be converted because of unsupported calculation type "%s".', - $args['sourceId'], - $args['type'] - ); - } -} diff --git a/src/Profile/Shopware/Logging/Log/UnsupportedShippingCalculationTypeLog.php b/src/Profile/Shopware/Logging/Log/UnsupportedShippingCalculationTypeLog.php new file mode 100644 index 000000000..138945fcb --- /dev/null +++ b/src/Profile/Shopware/Logging/Log/UnsupportedShippingCalculationTypeLog.php @@ -0,0 +1,30 @@ + + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace SwagMigrationAssistant\Profile\Shopware\Logging\Log; + +use Shopware\Core\Framework\Log\Package; +use SwagMigrationAssistant\Migration\Logging\Log\Builder\AbstractMigrationLogEntry; + +#[Package('fundamentals@after-sales')] +readonly class UnsupportedShippingCalculationTypeLog extends AbstractMigrationLogEntry +{ + public function isUserFixable(): bool + { + return false; + } + + public function getLevel(): string + { + return self::LOG_LEVEL_WARNING; + } + + public function getCode(): string + { + return 'SWAG_MIGRATION__SHOPWARE_UNSUPPORTED_SHIPPING_CALCULATION_TYPE'; + } +} diff --git a/src/Profile/Shopware/Logging/Log/UnsupportedShippingPriceLog.php b/src/Profile/Shopware/Logging/Log/UnsupportedShippingPriceLog.php index 20ef6a029..f77ee718a 100644 --- a/src/Profile/Shopware/Logging/Log/UnsupportedShippingPriceLog.php +++ b/src/Profile/Shopware/Logging/Log/UnsupportedShippingPriceLog.php @@ -8,18 +8,14 @@ namespace SwagMigrationAssistant\Profile\Shopware\Logging\Log; use Shopware\Core\Framework\Log\Package; -use SwagMigrationAssistant\Migration\Logging\Log\BaseRunLogEntry; +use SwagMigrationAssistant\Migration\Logging\Log\Builder\AbstractMigrationLogEntry; #[Package('fundamentals@after-sales')] -class UnsupportedShippingPriceLog extends BaseRunLogEntry +readonly class UnsupportedShippingPriceLog extends AbstractMigrationLogEntry { - public function __construct( - string $runId, - string $entity, - string $sourceId, - private readonly string $shippingMethodId, - ) { - parent::__construct($runId, $entity, $sourceId); + public function isUserFixable(): bool + { + return false; } public function getLevel(): string @@ -31,32 +27,4 @@ public function getCode(): string { return 'SWAG_MIGRATION__SHOPWARE_UNSUPPORTED_SHIPPING_PRICE'; } - - public function getTitle(): string - { - return 'Unsupported shipping factor price calculation'; - } - - /** - * @return array{entity: ?string, sourceId: ?string, shippingMethodId: string} - */ - public function getParameters(): array - { - return [ - 'entity' => $this->getEntity(), - 'sourceId' => $this->getSourceId(), - 'shippingMethodId' => $this->shippingMethodId, - ]; - } - - public function getDescription(): string - { - $args = $this->getParameters(); - - return \sprintf( - 'ShippingPrice-Entity with source id "%s" of shipping method "%s" could not be converted because of unsupported factor price calculation.', - $args['sourceId'], - $args['shippingMethodId'] - ); - } } diff --git a/src/Profile/Shopware/Logging/Log/UnsupportedTranslationType.php b/src/Profile/Shopware/Logging/Log/UnsupportedTranslationTypeLog.php similarity index 85% rename from src/Profile/Shopware/Logging/Log/UnsupportedTranslationType.php rename to src/Profile/Shopware/Logging/Log/UnsupportedTranslationTypeLog.php index 6f61a5bd6..c7bb3c133 100644 --- a/src/Profile/Shopware/Logging/Log/UnsupportedTranslationType.php +++ b/src/Profile/Shopware/Logging/Log/UnsupportedTranslationTypeLog.php @@ -8,10 +8,10 @@ namespace SwagMigrationAssistant\Profile\Shopware\Logging\Log; use Shopware\Core\Framework\Log\Package; -use SwagMigrationAssistant\Migration\Logging\Log\UnsupportedObjectType; +use SwagMigrationAssistant\Migration\Logging\Log\UnsupportedObjectTypeLog; #[Package('fundamentals@after-sales')] -class UnsupportedTranslationType extends UnsupportedObjectType +readonly class UnsupportedTranslationTypeLog extends UnsupportedObjectTypeLog { public function getLevel(): string { diff --git a/src/Profile/Shopware/Media/LocalMediaProcessor.php b/src/Profile/Shopware/Media/LocalMediaProcessor.php index e140d9f38..d23712cf7 100644 --- a/src/Profile/Shopware/Media/LocalMediaProcessor.php +++ b/src/Profile/Shopware/Media/LocalMediaProcessor.php @@ -10,12 +10,13 @@ use Doctrine\DBAL\Connection; use Shopware\Core\Content\Media\File\FileSaver; use Shopware\Core\Content\Media\File\MediaFile; +use Shopware\Core\Content\Media\MediaDefinition; use Shopware\Core\Content\Media\MediaException; use Shopware\Core\Framework\Context; use Shopware\Core\Framework\DataAbstractionLayer\EntityRepository; use Shopware\Core\Framework\Log\Package; use Shopware\Core\Framework\Uuid\Uuid; -use SwagMigrationAssistant\Migration\DataSelection\DefaultEntities; +use SwagMigrationAssistant\Migration\Logging\Log\Builder\MigrationLogBuilder; use SwagMigrationAssistant\Migration\Logging\Log\CannotGetFileRunLog; use SwagMigrationAssistant\Migration\Logging\Log\ExceptionRunLog; use SwagMigrationAssistant\Migration\Logging\Log\MimeTypeErrorLog; @@ -129,12 +130,17 @@ private function copyMediaFiles( if ($resolver === null) { $mappedWorkload[$mediaId]->setState(MediaProcessWorkloadStruct::ERROR_STATE); - $this->loggingService->addLogEntry(new CannotGetFileRunLog( - $mappedWorkload[$mediaId]->getRunId(), - DefaultEntities::MEDIA, - $mediaId, - $sourcePath - )); + $this->loggingService->addLogEntry( + MigrationLogBuilder::fromMigrationContext($migrationContext) + ->withEntityName(MediaDefinition::ENTITY_NAME) + ->withSourceData([ + 'media_id' => $mediaId, + 'source_path' => $sourcePath, + 'media' => $mediaFile, + ]) + ->withEntityId($mediaId) + ->build(CannotGetFileRunLog::class) + ); $processedMedia[] = $mediaId; $failedMedia[] = $mediaId; @@ -147,11 +153,18 @@ private function copyMediaFiles( if ($filePath === false) { $failedMedia[] = $mediaId; $mappedWorkload[$mediaId]->setState(MediaProcessWorkloadStruct::ERROR_STATE); - $this->loggingService->addLogEntry(new TemporaryFileErrorLog( - $mappedWorkload[$mediaId]->getRunId(), - DefaultEntities::MEDIA, - $mediaId, - )); + + $this->loggingService->addLogEntry( + MigrationLogBuilder::fromMigrationContext($migrationContext) + ->withEntityName(MediaDefinition::ENTITY_NAME) + ->withSourceData([ + 'media_id' => $mediaId, + 'source_path' => $sourcePath, + 'media' => $mediaFile, + ]) + ->withEntityId($mediaId) + ->build(TemporaryFileErrorLog::class) + ); continue; } @@ -162,6 +175,7 @@ private function copyMediaFiles( try { $this->persistFileToMedia( + $migrationContext, $filePath, $mediaFile, $fileSize, @@ -175,22 +189,35 @@ private function copyMediaFiles( } catch (\Exception $e) { $mappedWorkload[$mediaId]->setState(MediaProcessWorkloadStruct::ERROR_STATE); $failedMedia[] = $mediaId; - $this->loggingService->addLogEntry(new ExceptionRunLog( - $mappedWorkload[$mediaId]->getRunId(), - DefaultEntities::MEDIA, - $e, - $mediaId - )); + + $this->loggingService->addLogEntry( + MigrationLogBuilder::fromMigrationContext($migrationContext) + ->withEntityName(MediaDefinition::ENTITY_NAME) + ->withSourceData([ + 'media_id' => $mediaId, + 'source_path' => $sourcePath, + 'media' => $mediaFile, + ]) + ->withExceptionMessage($e->getMessage()) + ->withExceptionTrace($e->getTrace()) + ->withEntityId($mediaId) + ->build(ExceptionRunLog::class) + ); } \unlink($filePath); } else { $mappedWorkload[$mediaId]->setState(MediaProcessWorkloadStruct::ERROR_STATE); - $this->loggingService->addLogEntry(new CannotGetFileRunLog( - $mappedWorkload[$mediaId]->getRunId(), - DefaultEntities::MEDIA, - $mediaId, - $sourcePath - )); + $this->loggingService->addLogEntry( + MigrationLogBuilder::fromMigrationContext($migrationContext) + ->withEntityName(MediaDefinition::ENTITY_NAME) + ->withSourceData([ + 'media_id' => $mediaId, + 'source_path' => $sourcePath, + 'media' => $mediaFile, + ]) + ->withEntityId($mediaId) + ->build(CannotGetFileRunLog::class) + ); $failedMedia[] = $mediaId; } } @@ -207,6 +234,7 @@ private function copyMediaFiles( * @param list $failedMedia */ private function persistFileToMedia( + MigrationContextInterface $migrationContext, string $filePath, array $media, int $fileSize, @@ -217,14 +245,22 @@ private function persistFileToMedia( ): void { $mediaId = $media['media_id']; $mimeType = \mime_content_type($filePath); + if ($mimeType === false) { $failedMedia[] = $mediaId; $mappedWorkload[$mediaId]->setState(MediaProcessWorkloadStruct::ERROR_STATE); - $this->loggingService->addLogEntry(new MimeTypeErrorLog( - $mappedWorkload[$mediaId]->getRunId(), - DefaultEntities::MEDIA, - $mediaId - )); + + $this->loggingService->addLogEntry( + MigrationLogBuilder::fromMigrationContext($migrationContext) + ->withEntityName(MediaDefinition::ENTITY_NAME) + ->withSourceData([ + 'media_id' => $mediaId, + 'file_path' => $filePath, + 'media' => $media, + ]) + ->withEntityId($mediaId) + ->build(MimeTypeErrorLog::class) + ); return; } diff --git a/src/Profile/Shopware/Media/LocalOrderDocumentProcessor.php b/src/Profile/Shopware/Media/LocalOrderDocumentProcessor.php index 5c9cf2ab6..cea0b1fc1 100644 --- a/src/Profile/Shopware/Media/LocalOrderDocumentProcessor.php +++ b/src/Profile/Shopware/Media/LocalOrderDocumentProcessor.php @@ -8,13 +8,14 @@ namespace SwagMigrationAssistant\Profile\Shopware\Media; use Doctrine\DBAL\Connection; +use Shopware\Core\Content\Media\MediaDefinition; use Shopware\Core\Content\Media\MediaException; use Shopware\Core\Content\Media\MediaService; use Shopware\Core\Framework\Context; use Shopware\Core\Framework\DataAbstractionLayer\EntityRepository; use Shopware\Core\Framework\Log\Package; use Shopware\Core\Framework\Uuid\Uuid; -use SwagMigrationAssistant\Migration\DataSelection\DefaultEntities; +use SwagMigrationAssistant\Migration\Logging\Log\Builder\MigrationLogBuilder; use SwagMigrationAssistant\Migration\Logging\Log\CannotGetFileRunLog; use SwagMigrationAssistant\Migration\Logging\Log\ExceptionRunLog; use SwagMigrationAssistant\Migration\Logging\LoggingServiceInterface; @@ -66,12 +67,7 @@ public function process( private function getInstallationRoot(MigrationContextInterface $migrationContext): string { - $connection = $migrationContext->getConnection(); - if ($connection === null) { - return ''; - } - - $credentials = $connection->getCredentialFields(); + $credentials = $migrationContext->getConnection()->getCredentialFields(); if ($credentials === null) { return ''; @@ -101,12 +97,19 @@ private function copyMediaFiles( if (!\is_file($sourcePath)) { $mappedWorkload[$mediaId]->setState(MediaProcessWorkloadStruct::ERROR_STATE); - $this->loggingService->addLogEntry(new CannotGetFileRunLog( - $mappedWorkload[$mediaId]->getRunId(), - DefaultEntities::ORDER_DOCUMENT, - $mediaId, - $sourcePath - )); + + $this->loggingService->addLogEntry( + MigrationLogBuilder::fromMigrationContext($migrationContext) + ->withEntityName(MediaDefinition::ENTITY_NAME) + ->withSourceData([ + 'media_id' => $mediaId, + 'source_path' => $sourcePath, + 'media' => $mappedWorkload[$mediaId], + ]) + ->withEntityId($mediaId) + ->build(CannotGetFileRunLog::class) + ); + $processedMedia[] = $mediaId; $failedMedia[] = $mediaId; @@ -124,12 +127,18 @@ private function copyMediaFiles( $mappedWorkload[$mediaId]->setState(MediaProcessWorkloadStruct::ERROR_STATE); - $this->loggingService->addLogEntry(new ExceptionRunLog( - $mappedWorkload[$mediaId]->getRunId(), - DefaultEntities::ORDER_DOCUMENT, - $e, - $mediaId - )); + $this->loggingService->addLogEntry( + MigrationLogBuilder::fromMigrationContext($migrationContext) + ->withExceptionMessage($e->getMessage()) + ->withExceptionTrace($e->getTrace()) + ->withSourceData([ + 'media_id' => $mediaId, + 'source_path' => $sourcePath, + 'media' => $mappedWorkload[$mediaId], + ]) + ->withEntityId($mediaId) + ->build(ExceptionRunLog::class) + ); } } diff --git a/src/Profile/Shopware/Media/LocalProductDownloadProcessor.php b/src/Profile/Shopware/Media/LocalProductDownloadProcessor.php index 9f65904f3..820ef8fc4 100644 --- a/src/Profile/Shopware/Media/LocalProductDownloadProcessor.php +++ b/src/Profile/Shopware/Media/LocalProductDownloadProcessor.php @@ -8,6 +8,7 @@ namespace SwagMigrationAssistant\Profile\Shopware\Media; use Doctrine\DBAL\Connection; +use Shopware\Core\Content\Media\MediaDefinition; use Shopware\Core\Content\Media\MediaException; use Shopware\Core\Content\Media\MediaService; use Shopware\Core\Framework\Context; @@ -15,7 +16,7 @@ use Shopware\Core\Framework\Log\Package; use Shopware\Core\Framework\Uuid\Uuid; use SwagMigrationAssistant\Exception\MigrationException; -use SwagMigrationAssistant\Migration\DataSelection\DefaultEntities; +use SwagMigrationAssistant\Migration\Logging\Log\Builder\MigrationLogBuilder; use SwagMigrationAssistant\Migration\Logging\Log\CannotGetFileRunLog; use SwagMigrationAssistant\Migration\Logging\Log\ExceptionRunLog; use SwagMigrationAssistant\Migration\Logging\LoggingServiceInterface; @@ -71,12 +72,7 @@ public function process( private function getInstallationRoot(MigrationContextInterface $migrationContext): string { - $connection = $migrationContext->getConnection(); - if ($connection === null) { - return ''; - } - - $credentials = $connection->getCredentialFields(); + $credentials = $migrationContext->getConnection()->getCredentialFields(); if ($credentials === null) { return ''; @@ -106,12 +102,17 @@ private function copyMediaFiles( if (!\is_file($sourcePath)) { $mappedWorkload[$mediaId]->setState(MediaProcessWorkloadStruct::ERROR_STATE); - $this->loggingService->addLogEntry(new CannotGetFileRunLog( - $mappedWorkload[$mediaId]->getRunId(), - DefaultEntities::PRODUCT_DOWNLOAD, - $mediaId, - $sourcePath - )); + $this->loggingService->addLogEntry( + MigrationLogBuilder::fromMigrationContext($migrationContext) + ->withEntityName(MediaDefinition::ENTITY_NAME) + ->withSourceData([ + 'media_id' => $mediaId, + 'source_path' => $sourcePath, + 'media' => $mappedWorkload[$mediaId], + ]) + ->withEntityId($mediaId) + ->build(CannotGetFileRunLog::class) + ); $processedMedia[] = $mediaId; $failedMedia[] = $mediaId; @@ -129,12 +130,19 @@ private function copyMediaFiles( $mappedWorkload[$mediaId]->setState(MediaProcessWorkloadStruct::ERROR_STATE); - $this->loggingService->addLogEntry(new ExceptionRunLog( - $mappedWorkload[$mediaId]->getRunId(), - DefaultEntities::PRODUCT_DOWNLOAD, - $e, - $mediaId - )); + $this->loggingService->addLogEntry( + MigrationLogBuilder::fromMigrationContext($migrationContext) + ->withEntityName(MediaDefinition::ENTITY_NAME) + ->withSourceData([ + 'media_id' => $mediaId, + 'source_path' => $sourcePath, + 'media' => $mappedWorkload[$mediaId], + ]) + ->withExceptionMessage($e->getMessage()) + ->withExceptionTrace($e->getTrace()) + ->withEntityId($mediaId) + ->build(ExceptionRunLog::class) + ); } } diff --git a/src/Profile/Shopware/Media/Strategy/Md5StrategyResolver.php b/src/Profile/Shopware/Media/Strategy/Md5StrategyResolver.php index 0086edc00..89247a472 100644 --- a/src/Profile/Shopware/Media/Strategy/Md5StrategyResolver.php +++ b/src/Profile/Shopware/Media/Strategy/Md5StrategyResolver.php @@ -8,6 +8,7 @@ namespace SwagMigrationAssistant\Profile\Shopware\Media\Strategy; use Shopware\Core\Framework\Log\Package; +use Shopware\Core\Framework\Util\Hasher; use SwagMigrationAssistant\Migration\MigrationContextInterface; #[Package('fundamentals@after-sales')] @@ -24,12 +25,7 @@ public function supports(string $path, MigrationContextInterface $migrationConte public function resolve(string $path, MigrationContextInterface $migrationContext): string { - $connection = $migrationContext->getConnection(); - if ($connection === null) { - return ''; - } - - $credentials = $connection->getCredentialFields(); + $credentials = $migrationContext->getConnection()->getCredentialFields(); if ($credentials === null) { return ''; @@ -45,7 +41,7 @@ public function resolve(string $path, MigrationContextInterface $migrationContex $path = \ltrim($path, '/'); $pathElements = \explode('/', $path); $pathInfo = \pathinfo($path); - $md5hash = \md5($path); + $md5hash = Hasher::hash($path, 'md5'); if (empty($pathInfo['extension'])) { return ''; diff --git a/src/Profile/Shopware/Media/Strategy/PlainStrategyResolver.php b/src/Profile/Shopware/Media/Strategy/PlainStrategyResolver.php index 16381b1e8..31b97845b 100644 --- a/src/Profile/Shopware/Media/Strategy/PlainStrategyResolver.php +++ b/src/Profile/Shopware/Media/Strategy/PlainStrategyResolver.php @@ -20,12 +20,7 @@ public function supports(string $path, MigrationContextInterface $migrationConte public function resolve(string $path, MigrationContextInterface $migrationContext): string { - $connection = $migrationContext->getConnection(); - if ($connection === null) { - return ''; - } - - $credentials = $connection->getCredentialFields(); + $credentials = $migrationContext->getConnection()->getCredentialFields(); if ($credentials === null) { return ''; diff --git a/src/Profile/Shopware/Premapping/DefaultShippingAvailabilityRuleReader.php b/src/Profile/Shopware/Premapping/DefaultShippingAvailabilityRuleReader.php index ee326b4a5..59844bd50 100644 --- a/src/Profile/Shopware/Premapping/DefaultShippingAvailabilityRuleReader.php +++ b/src/Profile/Shopware/Premapping/DefaultShippingAvailabilityRuleReader.php @@ -63,12 +63,7 @@ public function getPremapping(Context $context, MigrationContextInterface $migra protected function fillConnectionPremappingValue(MigrationContextInterface $migrationContext): void { - $connection = $migrationContext->getConnection(); - if ($connection === null) { - return; - } - - $mappingArray = $connection->getPremapping(); + $mappingArray = $migrationContext->getConnection()->getPremapping(); if ($mappingArray === null) { return; diff --git a/src/Profile/Shopware/Premapping/DeliveryTimeReader.php b/src/Profile/Shopware/Premapping/DeliveryTimeReader.php index fcae802c6..735fa78e8 100644 --- a/src/Profile/Shopware/Premapping/DeliveryTimeReader.php +++ b/src/Profile/Shopware/Premapping/DeliveryTimeReader.php @@ -63,12 +63,7 @@ public function getPremapping(Context $context, MigrationContextInterface $migra protected function fillConnectionPremappingValue(MigrationContextInterface $migrationContext): void { - $connection = $migrationContext->getConnection(); - if ($connection === null) { - return; - } - - $mappingArray = $connection->getPremapping(); + $mappingArray = $migrationContext->getConnection()->getPremapping(); if ($mappingArray === null) { return; diff --git a/src/Profile/Shopware/Premapping/NewsletterRecipientStatusReader.php b/src/Profile/Shopware/Premapping/NewsletterRecipientStatusReader.php index 8c758576f..bac7f4f8f 100644 --- a/src/Profile/Shopware/Premapping/NewsletterRecipientStatusReader.php +++ b/src/Profile/Shopware/Premapping/NewsletterRecipientStatusReader.php @@ -47,12 +47,7 @@ public function getPremapping(Context $context, MigrationContextInterface $migra protected function fillConnectionPremappingValue(MigrationContextInterface $migrationContext): void { - $connection = $migrationContext->getConnection(); - if ($connection === null) { - return; - } - - $mappingArray = $connection->getPremapping(); + $mappingArray = $migrationContext->getConnection()->getPremapping(); if ($mappingArray === null) { return; diff --git a/src/Profile/Shopware/Premapping/TransactionStateReader.php b/src/Profile/Shopware/Premapping/TransactionStateReader.php index 75d84ed6f..0b33d3981 100644 --- a/src/Profile/Shopware/Premapping/TransactionStateReader.php +++ b/src/Profile/Shopware/Premapping/TransactionStateReader.php @@ -167,6 +167,7 @@ private function setPreselection(array $mapping): void private function getPreselectionValue(string $sourceId): ?string { $preselectionValue = null; + switch ((int) $sourceId) { case 9: // partially_invoiced $preselectionValue = $this->preselectionDictionary[OrderTransactionStates::STATE_OPEN] ?? null; diff --git a/src/Profile/Shopware54/Shopware54Profile.php b/src/Profile/Shopware54/Shopware54Profile.php index 7cee38651..9a182fc60 100644 --- a/src/Profile/Shopware54/Shopware54Profile.php +++ b/src/Profile/Shopware54/Shopware54Profile.php @@ -21,7 +21,7 @@ class Shopware54Profile implements ShopwareProfileInterface final public const AUTHOR_NAME = 'shopware AG'; - final public const ICON_PATH = '/swagmigrationassistant/static/img/migration-assistant-plugin.svg'; + final public const ICON_PATH = '/swagmigrationassistant/administration/static/img/migration-assistant-plugin.svg'; public function getName(): string { diff --git a/src/Profile/Shopware55/Shopware55Profile.php b/src/Profile/Shopware55/Shopware55Profile.php index 41122790f..67b867a28 100644 --- a/src/Profile/Shopware55/Shopware55Profile.php +++ b/src/Profile/Shopware55/Shopware55Profile.php @@ -21,7 +21,7 @@ class Shopware55Profile implements ShopwareProfileInterface final public const AUTHOR_NAME = 'shopware AG'; - final public const ICON_PATH = '/swagmigrationassistant/static/img/migration-assistant-plugin.svg'; + final public const ICON_PATH = '/swagmigrationassistant/administration/static/img/migration-assistant-plugin.svg'; public function getName(): string { diff --git a/src/Profile/Shopware56/Shopware56Profile.php b/src/Profile/Shopware56/Shopware56Profile.php index 8c01f0316..d95b9459d 100644 --- a/src/Profile/Shopware56/Shopware56Profile.php +++ b/src/Profile/Shopware56/Shopware56Profile.php @@ -21,7 +21,7 @@ class Shopware56Profile implements ShopwareProfileInterface final public const AUTHOR_NAME = 'shopware AG'; - final public const ICON_PATH = '/swagmigrationassistant/static/img/migration-assistant-plugin.svg'; + final public const ICON_PATH = '/swagmigrationassistant/administration/static/img/migration-assistant-plugin.svg'; public function getName(): string { diff --git a/src/Profile/Shopware57/Shopware57Profile.php b/src/Profile/Shopware57/Shopware57Profile.php index ad9f8769d..001e0e529 100644 --- a/src/Profile/Shopware57/Shopware57Profile.php +++ b/src/Profile/Shopware57/Shopware57Profile.php @@ -21,7 +21,7 @@ class Shopware57Profile implements ShopwareProfileInterface final public const AUTHOR_NAME = 'shopware AG'; - final public const ICON_PATH = '/swagmigrationassistant/static/img/migration-assistant-plugin.svg'; + final public const ICON_PATH = '/swagmigrationassistant/administration/static/img/migration-assistant-plugin.svg'; public function getName(): string { diff --git a/src/Profile/Shopware6/Converter/CategoryCmsPageAssociationConverter.php b/src/Profile/Shopware6/Converter/CategoryCmsPageAssociationConverter.php index 32a97bfe8..c0af9a249 100644 --- a/src/Profile/Shopware6/Converter/CategoryCmsPageAssociationConverter.php +++ b/src/Profile/Shopware6/Converter/CategoryCmsPageAssociationConverter.php @@ -40,10 +40,9 @@ protected function convertData(array $data): ConvertStruct $this->context ); - if ($mapping === null) { - return new ConvertStruct(null, $converted); + if ($mapping !== null) { + $converted['cmsPageId'] = $mapping['entityId']; } - $converted['cmsPageId'] = $mapping['entityUuid']; } return new ConvertStruct($converted, null, $this->mainMapping['id']); diff --git a/src/Profile/Shopware6/Converter/CmsPageConverter.php b/src/Profile/Shopware6/Converter/CmsPageConverter.php index d9dceea0f..fc63452bd 100644 --- a/src/Profile/Shopware6/Converter/CmsPageConverter.php +++ b/src/Profile/Shopware6/Converter/CmsPageConverter.php @@ -34,20 +34,18 @@ public function supports(MigrationContextInterface $migrationContext): bool && $this->getDataSetEntity($migrationContext) === CmsPageDataSet::getEntity(); } - protected function convertData(array $data): ConvertStruct + protected function convertData(array $data): ?ConvertStruct { - $converted = $data; - // handle locked default layouts - if (isset($converted['locked']) && $converted['locked'] === true) { + if (isset($data['locked']) && $data['locked'] === true) { $cmsPageMapping = $this->mappingService->getMapping($this->connectionId, DefaultEntities::CMS_PAGE, $data['id'], $this->context); if ($cmsPageMapping !== null) { - return new ConvertStruct(null, $data, $cmsPageMapping['id']); + return null; } $cmpPageUuid = $this->cmsPageLookup->getLockedByNamesAndType( - \array_column($converted['translations'], 'name'), - $converted['type'], + \array_column($data['translations'], 'name'), + $data['type'], $this->context ); @@ -60,9 +58,11 @@ protected function convertData(array $data): ConvertStruct $cmpPageUuid, ); - return new ConvertStruct(null, $data); + return null; } + $converted = $data; + $this->updateTranslations($converted); $this->mainMapping = $this->getOrCreateMappingMainCompleteFacade( DefaultEntities::CMS_PAGE, diff --git a/src/Profile/Shopware6/Converter/CustomerWishlistConverter.php b/src/Profile/Shopware6/Converter/CustomerWishlistConverter.php index 38df224eb..9a65a772d 100644 --- a/src/Profile/Shopware6/Converter/CustomerWishlistConverter.php +++ b/src/Profile/Shopware6/Converter/CustomerWishlistConverter.php @@ -35,12 +35,12 @@ protected function convertData(array $data): ConvertStruct $customerMapping = $this->getMappingIdFacade(DefaultEntities::CUSTOMER, $converted['customerId']); if ($customerMapping === null) { - return new ConvertStruct(null, $data); + $converted['customerId'] = null; } $salesChannelMapping = $this->getMappingIdFacade(DefaultEntities::SALES_CHANNEL, $converted['salesChannelId']); if ($salesChannelMapping === null) { - return new ConvertStruct(null, $data); + $converted['salesChannelId'] = null; } // products association could be empty and thus this array key might not be set diff --git a/src/Profile/Shopware6/Converter/DocumentBaseConfigConverter.php b/src/Profile/Shopware6/Converter/DocumentBaseConfigConverter.php index 43bc1a46d..9ce720233 100644 --- a/src/Profile/Shopware6/Converter/DocumentBaseConfigConverter.php +++ b/src/Profile/Shopware6/Converter/DocumentBaseConfigConverter.php @@ -17,7 +17,6 @@ use SwagMigrationAssistant\Migration\Media\MediaFileServiceInterface; use SwagMigrationAssistant\Migration\MigrationContextInterface; use SwagMigrationAssistant\Profile\Shopware6\DataSelection\DataSet\DocumentBaseConfigDataSet; -use SwagMigrationAssistant\Profile\Shopware6\Logging\Log\UnsupportedDocumentTypeLog; use SwagMigrationAssistant\Profile\Shopware6\Shopware6MajorProfile; #[Package('fundamentals@after-sales')] @@ -56,18 +55,15 @@ protected function convertData(array $data): ConvertStruct $converted = $data; $converted['documentTypeId'] = $this->documentTypeLookup->get($converted['documentType']['technicalName'], $this->context); - if ($converted['documentTypeId'] === null) { - $this->loggingService->addLogEntry(new UnsupportedDocumentTypeLog($this->runId, DefaultEntities::ORDER_DOCUMENT_BASE_CONFIG, $data['id'], $data['documentType']['technicalName'])); - - return new ConvertStruct(null, $data, $converted['id'] ?? null); - } - unset($converted['documentType']); - - if ($data['global']) { - $converted['id'] = $this->globalDocumentBaseConfigLookup->get($converted['documentTypeId'], $this->context); - if ($converted['id'] === null) { - $converted['id'] = $data['id']; + if ($converted['documentTypeId'] !== null) { + if ($data['global']) { + $converted['id'] = $this->globalDocumentBaseConfigLookup->get($converted['documentTypeId'], $this->context); + if ($converted['id'] === null) { + $converted['id'] = $data['id']; + } } + + unset($converted['documentType']); } $this->mainMapping = $this->getOrCreateMappingMainCompleteFacade( diff --git a/src/Profile/Shopware6/Converter/DocumentConverter.php b/src/Profile/Shopware6/Converter/DocumentConverter.php index 605c8279e..9885b3bc4 100644 --- a/src/Profile/Shopware6/Converter/DocumentConverter.php +++ b/src/Profile/Shopware6/Converter/DocumentConverter.php @@ -16,7 +16,6 @@ use SwagMigrationAssistant\Migration\Media\MediaFileServiceInterface; use SwagMigrationAssistant\Migration\MigrationContextInterface; use SwagMigrationAssistant\Profile\Shopware6\DataSelection\DataSet\DocumentDataSet; -use SwagMigrationAssistant\Profile\Shopware6\Logging\Log\UnsupportedDocumentTypeLog; use SwagMigrationAssistant\Profile\Shopware6\Shopware6MajorProfile; #[Package('fundamentals@after-sales')] @@ -62,15 +61,12 @@ protected function convertData(array $data): ConvertStruct ); $converted['documentTypeId'] = $this->documentTypeLookup->get($converted['documentType']['technicalName'], $this->context); - if ($converted['documentTypeId'] === null) { - $this->loggingService->addLogEntry(new UnsupportedDocumentTypeLog($this->runId, DefaultEntities::ORDER_DOCUMENT, $data['id'], $data['documentType']['technicalName'])); - - return new ConvertStruct(null, $data, $this->mainMapping['id'] ?? null); - } - unset($converted['documentType']); + if ($converted['documentTypeId'] !== null) { + if (isset($converted['config']['documentTypeId'])) { + $converted['config']['documentTypeId'] = $converted['documentTypeId']; + } - if (isset($converted['config']['documentTypeId'])) { - $converted['config']['documentTypeId'] = $converted['documentTypeId']; + unset($converted['documentType']); } if (isset($converted['documentMediaFile'])) { diff --git a/src/Profile/Shopware6/Converter/MailTemplateConverter.php b/src/Profile/Shopware6/Converter/MailTemplateConverter.php index f09fbc19e..4aaa75c19 100644 --- a/src/Profile/Shopware6/Converter/MailTemplateConverter.php +++ b/src/Profile/Shopware6/Converter/MailTemplateConverter.php @@ -16,7 +16,6 @@ use SwagMigrationAssistant\Migration\Mapping\MappingServiceInterface; use SwagMigrationAssistant\Migration\Media\MediaFileServiceInterface; use SwagMigrationAssistant\Migration\MigrationContextInterface; -use SwagMigrationAssistant\Profile\Shopware\Logging\Log\UnsupportedMailTemplateType; use SwagMigrationAssistant\Profile\Shopware6\DataSelection\DataSet\MailTemplateDataSet; use SwagMigrationAssistant\Profile\Shopware6\Shopware6MajorProfile; @@ -60,39 +59,29 @@ protected function convertData(array $data): ConvertStruct if (isset($converted['mailTemplateType']['technicalName'])) { $mailTemplateTypeMapping = $this->mappingService->getMapping($this->connectionId, DefaultEntities::MAIL_TEMPLATE_TYPE, $data['mailTemplateTypeId'], $this->context); if ($mailTemplateTypeMapping !== null) { - $typeUuid = $mailTemplateTypeMapping['entityUuid']; + $typeUuid = $mailTemplateTypeMapping['entityId']; } else { $typeUuid = $this->mailTemplateTypeLookup->get($converted['mailTemplateType']['technicalName'], $this->context); - if ($typeUuid === null) { - $this->loggingService->addLogEntry( - new UnsupportedMailTemplateType( - $this->runId, - $data['id'], - $converted['mailTemplateType']['technicalName'] - ) + if ($typeUuid !== null) { + $this->mappingService->createMapping( + $this->connectionId, + DefaultEntities::MAIL_TEMPLATE_TYPE, + $data['mailTemplateTypeId'], + $this->checksum, + null, + $typeUuid, ); - - return new ConvertStruct(null, $data, $converted['id'] ?? null); } - - $this->mappingService->createMapping( - $this->connectionId, - DefaultEntities::MAIL_TEMPLATE_TYPE, - $data['mailTemplateTypeId'], - $this->checksum, - null, - $typeUuid, - ); } - unset($converted['mailTemplateType']); $converted['mailTemplateTypeId'] = $typeUuid; + unset($converted['mailTemplateType']); } - if ($data['systemDefault']) { + if ($data['systemDefault'] && isset($converted['mailTemplateTypeId'])) { $defaultMailTemplateMapping = $this->mappingService->getMapping($this->connectionId, DefaultEntities::MAIL_TEMPLATE, $data['id'], $this->context); if ($defaultMailTemplateMapping !== null) { - $defaultMailTemplateUuid = $defaultMailTemplateMapping['entityUuid']; + $defaultMailTemplateUuid = $defaultMailTemplateMapping['entityId']; } else { $defaultMailTemplateUuid = $this->systemDefaultMailTemplateLookup->get($converted['mailTemplateTypeId'], $this->context); } diff --git a/src/Profile/Shopware6/Converter/MediaFolderConverter.php b/src/Profile/Shopware6/Converter/MediaFolderConverter.php index 995d03c21..3bd90dc13 100644 --- a/src/Profile/Shopware6/Converter/MediaFolderConverter.php +++ b/src/Profile/Shopware6/Converter/MediaFolderConverter.php @@ -7,9 +7,11 @@ namespace SwagMigrationAssistant\Profile\Shopware6\Converter; +use Shopware\Core\Content\Media\Aggregate\MediaFolder\MediaFolderDefinition; use Shopware\Core\Framework\Log\Package; use SwagMigrationAssistant\Migration\Converter\ConvertStruct; use SwagMigrationAssistant\Migration\DataSelection\DefaultEntities; +use SwagMigrationAssistant\Migration\Logging\Log\Builder\MigrationLogBuilder; use SwagMigrationAssistant\Migration\Logging\LoggingServiceInterface; use SwagMigrationAssistant\Migration\Mapping\Lookup\MediaDefaultFolderLookup; use SwagMigrationAssistant\Migration\Mapping\Lookup\MediaThumbnailSizeLookup; @@ -37,7 +39,7 @@ public function supports(MigrationContextInterface $migrationContext): bool && $this->getDataSetEntity($migrationContext) === MediaFolderDataSet::getEntity(); } - protected function convertData(array $data): ConvertStruct + protected function convertData(array $data): ?ConvertStruct { $converted = $data; @@ -51,7 +53,7 @@ protected function convertData(array $data): ConvertStruct // edge case for hidden download products media folder // this doesn't need to be migrated, just map the files into it // otherwise the code below would lead to a self-referential parentId - return new ConvertStruct(null, $data, $this->mainMapping['id'] ?? null); + return null; } if (isset($converted['defaultFolder'])) { @@ -59,12 +61,13 @@ protected function convertData(array $data): ConvertStruct if ($converted['parentId'] === null) { $this->loggingService->addLogEntry( - new UnsupportedMediaDefaultFolderLog( - $this->migrationContext->getRunUuid(), - DefaultEntities::MEDIA_FOLDER, - $data['id'], - $data['defaultFolder']['entity'] - ) + MigrationLogBuilder::fromMigrationContext($this->migrationContext) + ->withEntityName(MediaFolderDefinition::ENTITY_NAME) + ->withFieldName('parentId') + ->withFieldSourcePath('defaultFolder.entity') + ->withSourceData($data) + ->withConvertedData($converted) + ->build(UnsupportedMediaDefaultFolderLog::class) ); } diff --git a/src/Profile/Shopware6/Converter/NumberRangeConverter.php b/src/Profile/Shopware6/Converter/NumberRangeConverter.php index 98bc37218..1eecdb219 100644 --- a/src/Profile/Shopware6/Converter/NumberRangeConverter.php +++ b/src/Profile/Shopware6/Converter/NumberRangeConverter.php @@ -19,7 +19,6 @@ use SwagMigrationAssistant\Migration\Mapping\Lookup\NumberRangeTypeLookup; use SwagMigrationAssistant\Migration\Mapping\MappingServiceInterface; use SwagMigrationAssistant\Migration\MigrationContextInterface; -use SwagMigrationAssistant\Profile\Shopware\Logging\Log\UnsupportedNumberRangeTypeLog; use SwagMigrationAssistant\Profile\Shopware6\DataSelection\DataSet\NumberRangeDataSet; use SwagMigrationAssistant\Profile\Shopware6\Shopware6MajorProfile; @@ -52,34 +51,16 @@ protected function convertData(array $data): ConvertStruct if (isset($converted['type']['technicalName'])) { $numberRangeTypeMapping = $this->mappingService->getMapping($this->connectionId, DefaultEntities::NUMBER_RANGE_TYPE, $converted['type']['technicalName'], $this->context); if ($numberRangeTypeMapping !== null) { - $typeUuid = $numberRangeTypeMapping['entityUuid']; + $typeUuid = $numberRangeTypeMapping['entityId']; } else { $typeUuid = $this->numberRangeTypeLookup->get($converted['type']['technicalName'], $this->context); - if ($typeUuid === null) { - $this->mainMapping = $this->getOrCreateMappingMainCompleteFacade( - DefaultEntities::NUMBER_RANGE, - $data['id'], - $data['id'] - ); - - $this->loggingService->addLogEntry( - new UnsupportedNumberRangeTypeLog( - $this->runId, - DefaultEntities::NUMBER_RANGE, - $data['id'], - $converted['type']['technicalName'] - ) - ); - - return new ConvertStruct(null, $data, $this->mainMapping['id'] ?? null); - } } if ($converted['global']) { $this->checkForExistingNumberRange($converted); } - if (isset($converted['numberRangeSalesChannels'])) { + if (isset($converted['numberRangeSalesChannels']) && $typeUuid !== null) { foreach ($converted['numberRangeSalesChannels'] as &$numberRangeSalesChannel) { $numberRangeSalesChannel['numberRangeTypeId'] = $typeUuid; } diff --git a/src/Profile/Shopware6/Converter/ProductConverter.php b/src/Profile/Shopware6/Converter/ProductConverter.php index aff6ef54b..b9ba70600 100644 --- a/src/Profile/Shopware6/Converter/ProductConverter.php +++ b/src/Profile/Shopware6/Converter/ProductConverter.php @@ -139,6 +139,10 @@ protected function convertData(array $data): ConvertStruct if (isset($converted['configuratorSettings'])) { foreach ($converted['configuratorSettings'] as &$setting) { + if (!\is_array($setting)) { + continue; + } + if (isset($setting['price'])) { $this->updateAssociationIds( $setting['price'], @@ -147,7 +151,6 @@ protected function convertData(array $data): ConvertStruct DefaultEntities::PRODUCT ); - /** @phpstan-ignore-next-line */ $this->checkDefaultCurrency($setting, 'price'); } @@ -209,6 +212,9 @@ protected function convertData(array $data): ConvertStruct return new ConvertStruct($converted, null, $this->mainMapping['id'] ?? null); } + /** + * @param array $source + */ private function checkDefaultCurrency(array &$source, string $key): void { // If the default currency of source and destination is identically, there is no need to add a default price diff --git a/src/Profile/Shopware6/Converter/ProductSortingConverter.php b/src/Profile/Shopware6/Converter/ProductSortingConverter.php index 459b285f4..024b3a607 100644 --- a/src/Profile/Shopware6/Converter/ProductSortingConverter.php +++ b/src/Profile/Shopware6/Converter/ProductSortingConverter.php @@ -34,7 +34,7 @@ public function supports(MigrationContextInterface $migrationContext): bool && $this->getDataSetEntity($migrationContext) === ProductSortingDataSet::getEntity(); } - protected function convertData(array $data): ConvertStruct + protected function convertData(array $data): ?ConvertStruct { $converted = $data; $productSortingUuid = $this->productSortingLookup->get($data['key'], $this->context); @@ -50,7 +50,7 @@ protected function convertData(array $data): ConvertStruct ); if ($this->productSortingLookup->getIsLocked($data['key'], $this->context)) { - return new ConvertStruct(null, $data, $this->mainMapping['id'] ?? null); + return null; } $this->updateAssociationIds( diff --git a/src/Profile/Shopware6/Converter/SalesChannelConverter.php b/src/Profile/Shopware6/Converter/SalesChannelConverter.php index 6bac57c34..cfe101ee8 100644 --- a/src/Profile/Shopware6/Converter/SalesChannelConverter.php +++ b/src/Profile/Shopware6/Converter/SalesChannelConverter.php @@ -132,7 +132,6 @@ protected function convertData(array $data): ConvertStruct } unset( - // ToDo implement if these associations are migrated $converted['mailHeaderFooterId'] ); diff --git a/src/Profile/Shopware6/Converter/SalutationConverter.php b/src/Profile/Shopware6/Converter/SalutationConverter.php index dd0414066..ed362c360 100644 --- a/src/Profile/Shopware6/Converter/SalutationConverter.php +++ b/src/Profile/Shopware6/Converter/SalutationConverter.php @@ -40,7 +40,7 @@ protected function convertData(array $data): ConvertStruct $salutationMapping = $this->mappingService->getMapping($this->connectionId, DefaultEntities::SALUTATION, $data['id'], $this->context); if ($salutationMapping !== null) { - $salutationUuid = $salutationMapping['entityUuid']; + $salutationUuid = $salutationMapping['entityId']; } else { $salutationUuid = $this->salutationLookup->get($data['salutationKey'], $this->context); } diff --git a/src/Profile/Shopware6/Converter/SeoUrlConverter.php b/src/Profile/Shopware6/Converter/SeoUrlConverter.php index 06c2224a0..c35c6c246 100644 --- a/src/Profile/Shopware6/Converter/SeoUrlConverter.php +++ b/src/Profile/Shopware6/Converter/SeoUrlConverter.php @@ -33,34 +33,37 @@ public function supports(MigrationContextInterface $migrationContext): bool && $this->getDataSetEntity($migrationContext) === SeoUrlDataSet::getEntity(); } - protected function convertData(array $data): ConvertStruct + protected function convertData(array $data): ?ConvertStruct { if (isset($data['isModified']) && $data['isModified'] === false) { - return new ConvertStruct(null, $data); + return null; } $converted = $data; if (isset($converted['foreignKey'])) { + $relatedEntity = null; if ($converted['routeName'] === self::CATEGORY_ROUTE_NAME) { $relatedEntity = DefaultEntities::CATEGORY; } elseif ($converted['routeName'] === self::PRODUCT_ROUTE_NAME) { $relatedEntity = DefaultEntities::PRODUCT; - } else { - return new ConvertStruct(null, $converted); } - $converted['foreignKey'] = $this->getMappingIdFacade( - $relatedEntity, - $converted['foreignKey'] - ); + if ($relatedEntity !== null) { + $converted['foreignKey'] = $this->getMappingIdFacade( + $relatedEntity, + $converted['foreignKey'] + ); + } } - $this->mainMapping = $this->getOrCreateMappingMainCompleteFacade( - DefaultEntities::SEO_URL, - $data['id'], - $converted['id'] - ); + if (isset($data['id']) && isset($converted['id'])) { + $this->mainMapping = $this->getOrCreateMappingMainCompleteFacade( + DefaultEntities::SEO_URL, + $data['id'], + $converted['id'] + ); + } if (isset($converted['salesChannelId'])) { $converted['salesChannelId'] = $this->getMappingIdFacade( diff --git a/src/Profile/Shopware6/Converter/ShopwareConverter.php b/src/Profile/Shopware6/Converter/ShopwareConverter.php index d18af65cb..c9614992a 100644 --- a/src/Profile/Shopware6/Converter/ShopwareConverter.php +++ b/src/Profile/Shopware6/Converter/ShopwareConverter.php @@ -12,6 +12,7 @@ use SwagMigrationAssistant\Migration\Converter\Converter; use SwagMigrationAssistant\Migration\Converter\ConvertStruct; use SwagMigrationAssistant\Migration\Logging\Log\AssociationRequiredMissingLog; +use SwagMigrationAssistant\Migration\Logging\Log\Builder\MigrationLogBuilder; use SwagMigrationAssistant\Migration\Logging\LoggingServiceInterface; use SwagMigrationAssistant\Migration\Mapping\MappingServiceInterface; use SwagMigrationAssistant\Migration\MigrationContextInterface; @@ -41,16 +42,13 @@ public function getSourceIdentifier(array $data): string return $data['id']; } - public function convert(array $data, Context $context, MigrationContextInterface $migrationContext): ConvertStruct + public function convert(array $data, Context $context, MigrationContextInterface $migrationContext): ?ConvertStruct { $this->context = $context; $this->migrationContext = $migrationContext; $connection = $migrationContext->getConnection(); - $this->connectionId = ''; - if ($connection !== null) { - $this->connectionId = $connection->getId(); - } + $this->connectionId = $connection->getId(); $this->runId = $this->migrationContext->getRunUuid(); @@ -67,7 +65,7 @@ public function convert(array $data, Context $context, MigrationContextInterface /** * @param array $data */ - abstract protected function convertData(array $data): ConvertStruct; + abstract protected function convertData(array $data): ?ConvertStruct; protected function getMappingIdFacade(string $entityName, string $oldIdentifier): ?string { @@ -84,7 +82,7 @@ protected function getMappingIdFacade(string $entityName, string $oldIdentifier) $this->mappingIds[] = $mapping['id']; - return $mapping['entityUuid']; + return $mapping['entityId']; } protected function getOrCreateMappingIdFacade( @@ -104,11 +102,11 @@ protected function getOrCreateMappingIdFacade( $this->mappingIds[] = $mapping['id']; - return $mapping['entityUuid']; + return $mapping['entityId']; } /** - * @return array{id: string, connectionId: string, oldIdentifier: ?string, entityUuid: ?string, entityValue: ?string, checksum: ?string, additionalData: ?array} + * @return array{id: string, connectionId: string, oldIdentifier: ?string, entityId: ?string, entityValue: ?string, checksum: ?string, additionalData: ?array} */ protected function getOrCreateMappingMainCompleteFacade( string $entityName, @@ -147,12 +145,12 @@ protected function updateAssociationIds(array &$associationArray, string $entity if (empty($newAssociationId)) { if ($logMissing) { - $this->loggingService->addLogEntry(new AssociationRequiredMissingLog( - $this->runId, - $entity, - $oldAssociationId, - $sourceEntity - )); + $this->loggingService->addLogEntry( + MigrationLogBuilder::fromMigrationContext($this->migrationContext) + ->withEntityName($entity) + ->withConvertedData($association) + ->build(AssociationRequiredMissingLog::class) + ); } if ($unsetMissing) { diff --git a/src/Profile/Shopware6/Converter/TaxRuleConverter.php b/src/Profile/Shopware6/Converter/TaxRuleConverter.php index 7cc981e21..e63df5d88 100644 --- a/src/Profile/Shopware6/Converter/TaxRuleConverter.php +++ b/src/Profile/Shopware6/Converter/TaxRuleConverter.php @@ -44,19 +44,17 @@ protected function convertData(array $data): ConvertStruct DefaultEntities::TAX, $converted['taxId'] ); - if ($taxId === null) { - return new ConvertStruct(null, $converted); + if ($taxId !== null) { + $converted['taxId'] = $taxId; } - $converted['taxId'] = $taxId; $countryId = $this->getMappingIdFacade( DefaultEntities::COUNTRY, $converted['countryId'] ); - if ($countryId === null) { - return new ConvertStruct(null, $converted); + if ($countryId !== null) { + $converted['countryId'] = $countryId; } - $converted['countryId'] = $countryId; $taxRuleTypeMapping = $this->mappingService->getMapping( $this->connectionId, @@ -66,7 +64,7 @@ protected function convertData(array $data): ConvertStruct ); if ($taxRuleTypeMapping) { - $taxRuleTypeUuid = $taxRuleTypeMapping['entityUuid']; + $taxRuleTypeUuid = $taxRuleTypeMapping['entityId']; } else { $taxRuleTypeUuid = $this->taxRuleTypeLookup->get( $converted['type']['technicalName'] ?? '', @@ -84,11 +82,10 @@ protected function convertData(array $data): ConvertStruct } // new types can not be created due to write protection on technical name - if ($taxRuleTypeUuid === null) { - return new ConvertStruct(null, $converted); + if ($taxRuleTypeUuid !== null) { + $converted['taxRuleTypeId'] = $taxRuleTypeUuid; + unset($converted['type']); } - unset($converted['type']); - $converted['taxRuleTypeId'] = $taxRuleTypeUuid; $taxRuleId = $this->taxRuleLookup->get( $converted['taxId'], diff --git a/src/Profile/Shopware6/Gateway/Api/Reader/EnvironmentReader.php b/src/Profile/Shopware6/Gateway/Api/Reader/EnvironmentReader.php index 6d69efec2..75aa564c6 100644 --- a/src/Profile/Shopware6/Gateway/Api/Reader/EnvironmentReader.php +++ b/src/Profile/Shopware6/Gateway/Api/Reader/EnvironmentReader.php @@ -77,14 +77,14 @@ private function getEnvironment(): array return \json_decode($result->getBody()->getContents(), true); } catch (ClientException $e) { if ($e->getCode() === 401) { - throw MigrationException::invalidConnectionAuthentication('get-data'); + throw MigrationException::invalidConnectionCredentials('get-data'); } throw $e; } catch (RequestException $e) { if ($e->getRequest()->getUri()->getPath() === '/api/oauth/token') { // something went wrong with authentication. - throw MigrationException::invalidConnectionAuthentication('get-data'); + throw MigrationException::invalidConnectionCredentials('get-data'); } $response = $e->getResponse(); diff --git a/src/Profile/Shopware6/Gateway/Api/Shopware6ApiGateway.php b/src/Profile/Shopware6/Gateway/Api/Shopware6ApiGateway.php index 57b1ee52c..f1b290a00 100644 --- a/src/Profile/Shopware6/Gateway/Api/Shopware6ApiGateway.php +++ b/src/Profile/Shopware6/Gateway/Api/Shopware6ApiGateway.php @@ -19,6 +19,7 @@ use SwagMigrationAssistant\Migration\Gateway\Reader\EnvironmentReaderInterface; use SwagMigrationAssistant\Migration\Gateway\Reader\ReaderRegistryInterface; use SwagMigrationAssistant\Migration\MigrationContextInterface; +use SwagMigrationAssistant\Migration\Profile\ProfileInterface; use SwagMigrationAssistant\Profile\Shopware6\Gateway\ShopwareGatewayInterface; use SwagMigrationAssistant\Profile\Shopware6\Gateway\TableReaderInterface; use SwagMigrationAssistant\Profile\Shopware6\Gateway\TotalReaderInterface; @@ -54,9 +55,9 @@ public function getSnippetName(): string return 'swag-migration.wizard.pages.connectionCreate.gateways.shopwareApi'; } - public function supports(MigrationContextInterface $migrationContext): bool + public function supports(ProfileInterface $profile): bool { - return $migrationContext->getProfile() instanceof Shopware6ProfileInterface; + return $profile instanceof Shopware6ProfileInterface; } public function read(MigrationContextInterface $migrationContext): array @@ -83,20 +84,7 @@ public function readEnvironmentInformation(MigrationContextInterface $migrationC ); } - $connection = $migrationContext->getConnection(); - - if ($connection === null) { - return new EnvironmentInformation( - $profile->getSourceSystemName(), - $profile->getVersion(), - '', - [], - [], - null - ); - } - - $credentials = $connection->getCredentialFields(); + $credentials = $migrationContext->getConnection()->getCredentialFields(); if ($credentials === null) { return new EnvironmentInformation( @@ -157,7 +145,8 @@ public function readEnvironmentInformation(MigrationContextInterface $migrationC $targetSystemCurrency->getIsoCode(), $environmentDataArray['defaultCurrency'], $environmentDataArray['defaultShopLanguage'], - $targetSystemLocale->getCode() + $targetSystemLocale->getCode(), + $environmentDataArray['shopIdV2'] ?? null, ); } diff --git a/src/Profile/Shopware6/Gateway/Connection/AuthClient.php b/src/Profile/Shopware6/Gateway/Connection/AuthClient.php index 281988054..4f0657632 100644 --- a/src/Profile/Shopware6/Gateway/Connection/AuthClient.php +++ b/src/Profile/Shopware6/Gateway/Connection/AuthClient.php @@ -14,6 +14,7 @@ use Shopware\Core\Framework\Context; use Shopware\Core\Framework\DataAbstractionLayer\EntityRepository; use Shopware\Core\Framework\Log\Package; +use SwagMigrationAssistant\Exception\MigrationException; use SwagMigrationAssistant\Migration\Connection\SwagMigrationConnectionCollection; use SwagMigrationAssistant\Migration\Gateway\HttpClientInterface; use SwagMigrationAssistant\Migration\MigrationContext; @@ -95,16 +96,10 @@ private function setupBearerTokenIfNeeded(): void private function renewBearerToken(): void { - $connection = $this->migrationContext->getConnection(); - - if ($connection === null) { - return; // TODO: throw exception - } - - $credentials = $connection->getCredentialFields(); + $credentials = $this->migrationContext->getConnection()->getCredentialFields(); if ($credentials === null) { - return; // TODO: throw exception + throw MigrationException::invalidConnectionCredentials(); } $response = $this->apiClient->post('/api/oauth/token', [ @@ -126,25 +121,20 @@ private function renewBearerToken(): void private function saveBearerToken(): void { $connection = $this->migrationContext->getConnection(); + $credentials = $connection->getCredentialFields(); - if ($connection === null) { - return; - } - - $credentialFields = $connection->getCredentialFields(); - - if ($credentialFields === null) { - return; + if ($credentials === null) { + throw MigrationException::invalidConnectionCredentials(); } $connectionUuid = $connection->getId(); - $credentialFields['bearer_token'] = $this->bearerToken; + $credentials['bearer_token'] = $this->bearerToken; - $this->context->scope(MigrationContext::SOURCE_CONTEXT, function (Context $context) use ($connectionUuid, $credentialFields): void { + $this->context->scope(MigrationContext::SOURCE_CONTEXT, function (Context $context) use ($connectionUuid, $credentials): void { $this->connectionRepository->update([ [ 'id' => $connectionUuid, - 'credentialFields' => $credentialFields, + 'credentialFields' => $credentials, ], ], $context); }); @@ -152,15 +142,7 @@ private function saveBearerToken(): void private function loadBearerToken(): void { - $connection = $this->migrationContext->getConnection(); - - if ($connection === null) { - $this->renewBearerToken(); - - return; - } - - $credentials = $connection->getCredentialFields(); + $credentials = $this->migrationContext->getConnection()->getCredentialFields(); if ($credentials === null) { $this->renewBearerToken(); diff --git a/src/Profile/Shopware6/Gateway/Connection/ConnectionFactory.php b/src/Profile/Shopware6/Gateway/Connection/ConnectionFactory.php index 4869e07a5..5c6019c1b 100644 --- a/src/Profile/Shopware6/Gateway/Connection/ConnectionFactory.php +++ b/src/Profile/Shopware6/Gateway/Connection/ConnectionFactory.php @@ -29,13 +29,7 @@ public function __construct(private readonly EntityRepository $connectionReposit public function createApiClient(MigrationContextInterface $migrationContext): ?HttpClientInterface { - $connection = $migrationContext->getConnection(); - - if ($connection === null) { - return null; - } - - $credentials = $connection->getCredentialFields(); + $credentials = $migrationContext->getConnection()->getCredentialFields(); if (empty($credentials) || !isset($credentials['endpoint'])) { return null; @@ -50,7 +44,7 @@ public function createApiClient(MigrationContextInterface $migrationContext): ?H new Client($options), $this->connectionRepository, $migrationContext, - Context::createDefaultContext() // ToDo maybe replace this with the real context from the request, because this could cause caching issues (but it will only write data to DB). + Context::createDefaultContext() ); } } diff --git a/src/Profile/Shopware6/Logging/Log/UnsupportedDocumentTypeLog.php b/src/Profile/Shopware6/Logging/Log/UnsupportedDocumentTypeLog.php index 34a79374c..00063074c 100644 --- a/src/Profile/Shopware6/Logging/Log/UnsupportedDocumentTypeLog.php +++ b/src/Profile/Shopware6/Logging/Log/UnsupportedDocumentTypeLog.php @@ -8,18 +8,14 @@ namespace SwagMigrationAssistant\Profile\Shopware6\Logging\Log; use Shopware\Core\Framework\Log\Package; -use SwagMigrationAssistant\Migration\Logging\Log\BaseRunLogEntry; +use SwagMigrationAssistant\Migration\Logging\Log\Builder\AbstractMigrationLogEntry; #[Package('fundamentals@after-sales')] -class UnsupportedDocumentTypeLog extends BaseRunLogEntry +readonly class UnsupportedDocumentTypeLog extends AbstractMigrationLogEntry { - public function __construct( - string $runId, - string $entity, - string $sourceId, - private readonly string $technicalName, - ) { - parent::__construct($runId, $entity, $sourceId); + public function isUserFixable(): bool + { + return false; } public function getLevel(): string @@ -31,29 +27,4 @@ public function getCode(): string { return 'SWAG_MIGRATION__SHOPWARE_UNSUPPORTED_DOCUMENT_TYPE'; } - - public function getTitle(): string - { - return 'Unsupported document type'; - } - - public function getParameters(): array - { - return [ - 'entity' => $this->getEntity(), - 'sourceId' => $this->getSourceId(), - 'technicalName' => $this->technicalName, - ]; - } - - public function getDescription(): string - { - $args = $this->getParameters(); - - return \sprintf( - 'Document with source id "%s" could not be converted because of unsupported document type: %s.', - $args['sourceId'], - $args['technicalName'] - ); - } } diff --git a/src/Profile/Shopware6/Logging/Log/UnsupportedMediaDefaultFolderLog.php b/src/Profile/Shopware6/Logging/Log/UnsupportedMediaDefaultFolderLog.php index 7ca19bda8..122182b78 100644 --- a/src/Profile/Shopware6/Logging/Log/UnsupportedMediaDefaultFolderLog.php +++ b/src/Profile/Shopware6/Logging/Log/UnsupportedMediaDefaultFolderLog.php @@ -8,18 +8,14 @@ namespace SwagMigrationAssistant\Profile\Shopware6\Logging\Log; use Shopware\Core\Framework\Log\Package; -use SwagMigrationAssistant\Migration\Logging\Log\BaseRunLogEntry; +use SwagMigrationAssistant\Migration\Logging\Log\Builder\AbstractMigrationLogEntry; #[Package('fundamentals@after-sales')] -class UnsupportedMediaDefaultFolderLog extends BaseRunLogEntry +readonly class UnsupportedMediaDefaultFolderLog extends AbstractMigrationLogEntry { - public function __construct( - string $runId, - string $entity, - string $sourceId, - private readonly string $defaultEntity, - ) { - parent::__construct($runId, $entity, $sourceId); + public function isUserFixable(): bool + { + return false; } public function getLevel(): string @@ -31,29 +27,4 @@ public function getCode(): string { return 'SWAG_MIGRATION__SHOPWARE_UNSUPPORTED_MEDIA_DEFAULT_FOLDER'; } - - public function getTitle(): string - { - return 'Unsupported default media folder'; - } - - public function getParameters(): array - { - return [ - 'entity' => $this->getEntity(), - 'sourceId' => $this->getSourceId(), - 'defaultEntity' => $this->defaultEntity, - ]; - } - - public function getDescription(): string - { - $args = $this->getParameters(); - - return \sprintf( - 'Media Folder with source id "%s" could not be converted because of unsupported default folder for entity: %s.', - $args['sourceId'], - $args['defaultEntity'] - ); - } } diff --git a/src/Profile/Shopware6/Media/HttpOrderDocumentGenerationService.php b/src/Profile/Shopware6/Media/HttpOrderDocumentGenerationService.php index b49ae8d10..3283a7852 100644 --- a/src/Profile/Shopware6/Media/HttpOrderDocumentGenerationService.php +++ b/src/Profile/Shopware6/Media/HttpOrderDocumentGenerationService.php @@ -20,6 +20,7 @@ use SwagMigrationAssistant\Migration\Connection\SwagMigrationConnectionEntity; use SwagMigrationAssistant\Migration\DataSelection\DefaultEntities; use SwagMigrationAssistant\Migration\Gateway\HttpClientInterface; +use SwagMigrationAssistant\Migration\Logging\Log\Builder\MigrationLogBuilder; use SwagMigrationAssistant\Migration\Logging\Log\CannotGetFileRunLog; use SwagMigrationAssistant\Migration\Logging\Log\ExceptionRunLog; use SwagMigrationAssistant\Migration\Logging\LoggingServiceInterface; @@ -70,13 +71,7 @@ public function process( $mappedWorkload = []; $documentIds = []; $runId = $migrationContext->getRunUuid(); - $connection = $migrationContext->getConnection(); - - if ($connection === null) { - return $workload; - } - - $this->connection = $connection; + $this->connection = $migrationContext->getConnection(); foreach ($workload as $work) { $mappedWorkload[$work->getMediaId()] = $work; @@ -89,11 +84,14 @@ public function process( $client = $this->connectionFactory->createApiClient($migrationContext); if ($client === null) { - $this->loggingService->addLogEntry(new ExceptionRunLog( - $runId, - DefaultEntities::ORDER_DOCUMENT_GENERATED, - new \Exception('Connection to the source system could not be established') - )); + $exception = new \Exception('Connection to the source system could not be established'); + + $this->loggingService->addLogEntry( + MigrationLogBuilder::fromMigrationContext($migrationContext) + ->withExceptionMessage($exception->getMessage()) + ->withExceptionTrace($exception->getTrace()) + ->build(ExceptionRunLog::class) + ); $this->loggingService->saveLogging($context); return $workload; @@ -125,7 +123,15 @@ function (MediaProcessWorkloadStruct $work) use ($uuid) { } if ($state !== 'fulfilled') { - $this->handleFailedRequest($oldWorkload, $mappedWorkload[$uuid], $uuid, $additionalData, $failureUuids, $result['reason'] ?? null); + $this->handleFailedRequest( + $migrationContext, + $oldWorkload, + $mappedWorkload[$uuid], + $uuid, + $additionalData, + $failureUuids, + $result['reason'] ?? null + ); continue; } @@ -211,7 +217,7 @@ private function handleCompleteRequest(Context $context, array $result, string $ $mediaId = null; if ($mapping !== null) { - $mediaId = $mapping['entityUuid']; + $mediaId = $mapping['entityId']; } $context->scope(Context::SYSTEM_SCOPE, function (Context $context) use ( @@ -266,6 +272,7 @@ private function handleCompleteRequest(Context $context, array $result, string $ * @param list $failureUuids */ private function handleFailedRequest( + MigrationContextInterface $migrationContext, MediaProcessWorkloadStruct $oldWorkload, MediaProcessWorkloadStruct &$mappedWorkload, string $uuid, @@ -280,13 +287,15 @@ private function handleFailedRequest( if ($mappedWorkload->getErrorCount() > ProcessMediaHandler::MEDIA_ERROR_THRESHOLD) { $failureUuids[] = $uuid; $mappedWorkload->setState(MediaProcessWorkloadStruct::ERROR_STATE); - $this->loggingService->addLogEntry(new CannotGetFileRunLog( - $mappedWorkload->getRunId(), - DefaultEntities::ORDER_DOCUMENT, - $mappedWorkload->getMediaId(), - $mappedWorkload->getAdditionalData()['uri'], - $clientException - )); + + $this->loggingService->addLogEntry( + MigrationLogBuilder::fromMigrationContext($migrationContext) + ->withExceptionMessage($clientException?->getMessage() ?? 'Unknown error occurred') + ->withExceptionTrace($clientException?->getTrace() ?? []) + ->withSourceData($additionalData) + ->withEntityId($uuid) + ->build(CannotGetFileRunLog::class) + ); } } } diff --git a/src/Profile/Shopware6/Shopware6MajorProfile.php b/src/Profile/Shopware6/Shopware6MajorProfile.php index da28cfcfe..6684432fb 100644 --- a/src/Profile/Shopware6/Shopware6MajorProfile.php +++ b/src/Profile/Shopware6/Shopware6MajorProfile.php @@ -18,7 +18,7 @@ class Shopware6MajorProfile implements Shopware6ProfileInterface final public const AUTHOR_NAME = 'shopware AG'; - final public const ICON_PATH = '/swagmigrationassistant/static/img/migration-assistant-plugin.svg'; + final public const ICON_PATH = '/swagmigrationassistant/administration/static/img/migration-assistant-plugin.svg'; private string $supportedVersion; diff --git a/src/Resources/app/administration/.babelrc b/src/Resources/app/administration/.babelrc deleted file mode 100644 index 6acfb73e1..000000000 --- a/src/Resources/app/administration/.babelrc +++ /dev/null @@ -1,54 +0,0 @@ -{ - "presets": [ - [ - "@babel/preset-env", - { - "modules": false, - "useBuiltIns": "usage", - "corejs": 2 - } - ], - "@babel/preset-typescript" - ], - "plugins": [ - "@babel/plugin-transform-runtime", - "@babel/plugin-syntax-dynamic-import", - "@babel/plugin-syntax-import-meta", - "@babel/plugin-proposal-class-properties", - "@babel/plugin-proposal-json-strings", - [ - "@babel/plugin-proposal-decorators", - { - "legacy": true - } - ], - "@babel/plugin-proposal-function-sent", - "@babel/plugin-proposal-export-namespace-from", - "@babel/plugin-proposal-numeric-separator", - "@babel/plugin-proposal-throw-expressions" - ], - "comments": true, - "env": { - "test": { - "presets": [ - "@babel/preset-env" - ], - "plugins": [ - "@babel/plugin-syntax-dynamic-import", - "@babel/plugin-syntax-import-meta", - "@babel/plugin-proposal-class-properties", - "@babel/plugin-proposal-json-strings", - [ - "@babel/plugin-proposal-decorators", - { - "legacy": true - } - ], - "@babel/plugin-proposal-function-sent", - "@babel/plugin-proposal-export-namespace-from", - "@babel/plugin-proposal-numeric-separator", - "@babel/plugin-proposal-throw-expressions" - ] - } - } -} diff --git a/src/Resources/app/administration/.eslintignore b/src/Resources/app/administration/.eslintignore index 7ca12e18c..091ca3779 100644 --- a/src/Resources/app/administration/.eslintignore +++ b/src/Resources/app/administration/.eslintignore @@ -1,4 +1,3 @@ /node_modules /static -*.spec.vue2.js -*.fixtures.js +/.tmp diff --git a/src/Resources/app/administration/.eslintrc.js b/src/Resources/app/administration/.eslintrc.js index 81cb27b35..8efbd7199 100644 --- a/src/Resources/app/administration/.eslintrc.js +++ b/src/Resources/app/administration/.eslintrc.js @@ -1,275 +1,82 @@ /** - * @package admin + * @package fundamentals@after-sales */ - -const path = require('path'); - -const baseRules = { - // Disabled because it hides some warnings - 'file-progress/activate': 0, - // Match the max line length with the phpstorm default settings - 'max-len': ['error', 125, { ignoreRegExpLiterals: true }], - // Warn about useless path segment in import statements - 'import/no-useless-path-segments': 0, - // don't require .vue and .js extensions - 'import/extensions': ['error', 'always', { - js: 'never', - ts: 'never', - vue: 'never', - }], - 'no-console': ['error', { allow: ['warn', 'error'] }], - 'no-warning-comments': ['error', { location: 'anywhere' }], - 'inclusive-language/use-inclusive-words': 'error', - 'comma-dangle': ['error', 'always-multiline'], - 'sw-core-rules/require-position-identifier': ['error', { - components: [ - 'sw-card', - 'sw-tabs', - 'sw-extension-component-section', - ], - }], - 'sw-deprecation-rules/private-feature-declarations': 'error', - 'no-restricted-exports': 'off', - 'filename-rules/match': [2, /^(?!.*\.spec\.ts$).*(?:\.js|\.ts|\.html|\.html\.twig)$/], - 'vue/multi-word-component-names': ['error', { - ignores: ['index.html'], - }], -}; - module.exports = { root: true, - extends: [ - '@shopware-ag/eslint-config-base', - ], env: { browser: true, - 'jest/globals': true, }, - globals: { Shopware: true, - VueJS: true, - Cypress: true, - cy: true, - autoStub: true, - flushPromises: true, - wrapTestComponent: true, - resetFilters: true, }, - + extends: [ + '@shopware-ag/eslint-config-base', + 'eslint:recommended', + 'plugin:@typescript-eslint/recommended', + 'plugin:vue/vue3-recommended', + 'prettier', + ], plugins: [ - 'jest', - 'twig-vue', + '@typescript-eslint', 'inclusive-language', 'vuejs-accessibility', 'file-progress', - 'sw-core-rules', - 'sw-deprecation-rules', - 'sw-test-rules', 'filename-rules', + 'vue', + 'html', ], - + parser: '@typescript-eslint/parser', settings: { 'import/resolver': { - node: {}, - webpack: { - config: { - // Sync with webpack.config.js - resolve: { - extensions: ['.js', '.ts', '.vue', '.json', '.less', '.twig'], - alias: { - vue$: 'vue/dist/vue.esm.js', - src: path.join(__dirname, 'src'), - module: path.join(__dirname, 'src/module'), - scss: path.join(__dirname, 'src/app/assets/scss'), - assets: path.join(__dirname, 'static'), - // Alias for externals - Shopware: path.join(__dirname, 'src/core/shopware'), - '@administration': path.join(__dirname, 'src'), - }, - }, - }, + node: { + extensions: ['.js', '.ts', '.vue', '.json', '.less', '.twig'], }, }, }, - rules: { - ...baseRules, + quotes: ['error', 'single', { avoidEscape: true }], + semi: ['error', 'always'], + 'comma-dangle': ['error', 'always-multiline'], + 'max-len': ['error', 125, { + ignoreRegExpLiterals: true, + ignoreComments: false, + ignoreStrings: true, + ignoreTemplateLiterals: true, + ignoreUrls: true, + }], + 'no-console': ['error', { allow: ['warn', 'error'] }], + 'no-debugger': 'error', + 'no-var': 'error', + 'prefer-const': 'error', + 'prefer-arrow-callback': 'error', + 'arrow-spacing': ['error', { before: true, after: true }], + 'no-empty-function': 'error', + 'import/extensions': [ + 'error', + 'ignorePackages', + { js: 'never', ts: 'never' }, + ], + 'no-void': 'off', + 'no-unused-vars': 'off', + '@typescript-eslint/no-unused-vars': ['error', { argsIgnorePattern: '^_' }], + '@typescript-eslint/explicit-function-return-type': ['error', { allowExpressions: true }], + '@typescript-eslint/no-explicit-any': 'error', + '@typescript-eslint/consistent-type-imports': 'error', + '@typescript-eslint/ban-ts-comment': 'off', + 'implicit-arrow-linebreak': 'off', + 'function-paren-newline': 'off', }, - overrides: [ { - extends: [ - 'plugin:vue/vue3-recommended', - '@shopware-ag/eslint-config-base', - ], - files: ['**/*.js'], - excludedFiles: ['*.spec.js', '*.spec.vue3.js'], - parser: '@typescript-eslint/parser', - parserOptions: { - project: true, - tsconfigRootDir: __dirname, - }, + files: ['*.ts', '*.vue'], rules: { - ...baseRules, - '@typescript-eslint/no-floating-promises': 'warn', - 'vue/require-prop-types': 'error', - 'vue/require-default-prop': 'error', - 'vue/no-mutating-props': 'error', - 'vue/component-definition-name-casing': ['error', 'kebab-case'], - 'vue/no-boolean-default': ['error', 'default-false'], - 'vue/order-in-components': ['error', { - order: [ - 'el', - 'name', - 'parent', - 'functional', - ['template', 'render'], - 'inheritAttrs', - ['provide', 'inject'], - 'extends', - 'mixins', - 'model', - ['components', 'directives', 'filters'], - ['props', 'propsData'], - 'data', - 'metaInfo', - 'computed', - 'watch', - 'LIFECYCLE_HOOKS', - 'methods', - ['delimiters', 'comments'], - 'renderError', - ], - }], + '@typescript-eslint/explicit-module-boundary-types': 'error', }, - }, { - extends: [ - 'plugin:vue/vue3-recommended', - 'plugin:vue/essential', - 'plugin:vue/recommended', - 'eslint:recommended', - 'plugin:vuejs-accessibility/recommended', - ], - processor: 'twig-vue/twig-vue', - files: ['src/**/*.html.twig', 'test/eslint/**/*.html.twig'], - rules: { - 'vue/component-name-in-template-casing': ['error', 'kebab-case', { - registeredComponentsOnly: true, - ignores: [], - }], - 'vue/html-indent': ['error', 4, { - baseIndent: 0, - }], - 'no-multiple-empty-lines': ['error', { max: 1 }], - 'vue/attribute-hyphenation': 'error', - 'vue/multiline-html-element-content-newline': 'off', // allow more spacy templates - 'vue/html-self-closing': ['error', { - html: { - void: 'never', - normal: 'never', - component: 'always', - }, - svg: 'always', - math: 'always', - }], - 'vue/no-parsing-error': ['error', { - 'nested-comment': false, - }], - 'vue/valid-v-slot': ['error', { - allowModifiers: true, - }], - 'vue/v-slot-style': 'error', - 'vue/attributes-order': 'error', - 'vue/no-deprecated-slot-attribute': ['error'], - 'vue/no-deprecated-slot-scope-attribute': ['error'], - // eslint-disable-next-line no-warning-comments - // TODO: Make this error when all components are migrated to meteor - 'sw-deprecation-rules/no-deprecated-components': ['warn'], - 'sw-deprecation-rules/no-deprecated-component-usage': ['warn'], - 'vue/no-useless-template-attributes': 'error', - 'vue/no-lone-template': 'error', - - // Disabled rules - 'eol-last': 'off', // no newline required at the end of file - 'max-len': 'off', - 'vue/no-multiple-template-root': 'off', - 'vue/no-unused-vars': 'off', - 'vue/no-template-shadow': 'off', - 'vue/no-v-html': 'off', - 'vue/valid-template-root': 'off', - 'vue/no-v-model-argument': 'off', - 'vue/no-v-for-template-key': 'off', - 'vue/no-deprecated-filter': 'error', - - // doesn't play nicely with our twig blocks - 'vue/html-closing-bracket-newline': 'off', - 'vue/first-attribute-linebreak': 'off', - }, - }, { - files: ['**/*.spec.js', '**/*.spec.vue3.js', '**/fixtures/*.js', 'test/**/*.js', 'test/**/*.ts'], - rules: { - 'sw-test-rules/await-async-functions': 'error', - 'max-len': 0, - 'sw-deprecation-rules/private-feature-declarations': 0, - 'jest/expect-expect': 'error', - 'jest/no-duplicate-hooks': 'error', - 'jest/no-test-return-statement': 'error', - 'jest/prefer-hooks-in-order': 'error', - 'jest/prefer-hooks-on-top': 'error', - 'jest/prefer-to-be': 'error', - 'jest/require-top-level-describe': 'error', - 'jest/prefer-to-contain': 'error', - 'jest/prefer-to-have-length': 'error', - 'jest/consistent-test-it': ['error', { fn: 'it', withinDescribe: 'it' }], - }, - extends: ['plugin:jest/recommended'], - }, { - files: ['**/snippet/*.json'], - rules: { - 'inclusive-language/use-inclusive-words': 'error', - }, - }, { - files: ['**/*.ts', '**/*.tsx'], - extends: [ - '@shopware-ag/eslint-config-base', - 'plugin:@typescript-eslint/eslint-recommended', - 'plugin:@typescript-eslint/recommended', - 'plugin:@typescript-eslint/recommended-requiring-type-checking', - ], - parser: '@typescript-eslint/parser', - parserOptions: { - tsconfigRootDir: __dirname, - project: ['./tsconfig.json'], - }, - plugins: ['@typescript-eslint'], + }, + { + files: ['*.spec.ts', '*.test.ts'], rules: { - ...baseRules, - '@typescript-eslint/ban-ts-comment': 0, - '@typescript-eslint/no-unsafe-member-access': 'error', - '@typescript-eslint/no-unsafe-call': 'error', - '@typescript-eslint/no-unsafe-assignment': 'error', - '@typescript-eslint/no-unsafe-return': 'error', - '@typescript-eslint/explicit-module-boundary-types': 0, - '@typescript-eslint/prefer-ts-expect-error': 'error', - 'no-shadow': 'off', - '@typescript-eslint/no-shadow': ['error'], - '@typescript-eslint/consistent-type-imports': ['error'], - '@typescript-eslint/no-floating-promises': 'warn', - 'import/extensions': [ - 'error', - 'ignorePackages', - { - js: 'never', - jsx: 'never', - ts: 'never', - tsx: 'never', - }, - ], - 'no-void': 'off', - // Disable the base rule as it can report incorrect errors - 'no-unused-vars': 'off', - '@typescript-eslint/no-unused-vars': 'error', + '@typescript-eslint/no-empty-function': 'off', }, }, ], diff --git a/src/Resources/app/administration/.stylelintrc b/src/Resources/app/administration/.stylelintrc new file mode 100644 index 000000000..6353db612 --- /dev/null +++ b/src/Resources/app/administration/.stylelintrc @@ -0,0 +1,41 @@ +{ + "extends": "stylelint-config-standard-scss", + "ignoreFiles": [ + "node_modules/" + ], + "rules": { + "indentation": 4, + "color-hex-case": "lower", + "no-missing-end-of-source-newline": true, + "property-no-unknown": [true, { + "severity": "warning", + "ignoreProperties": [ + "user-focus", + "user-input", + "user-modify" + ] + }], + "no-descending-specificity": null, + "max-nesting-depth": [4, { + "ignore": ["blockless-at-rules", "pseudo-classes"], + "severity": "warning" + }], + "at-rule-no-unknown": null, + "scss/at-rule-no-unknown": true, + "selector-class-pattern": null, + "color-function-notation": "legacy", + "declaration-block-no-redundant-longhand-properties": null, + "scss/no-global-function-names": null, + "property-no-vendor-prefix": null, + "custom-property-pattern": null, + "max-line-length": [ + 120, + { + "severity": "warning" + } + ], + "scss/dollar-variable-pattern": null, + "selector-id-pattern": null, + "keyframes-name-pattern": null + } +} diff --git a/src/Resources/app/administration/package-lock.json b/src/Resources/app/administration/package-lock.json index 39274afe6..e7ad527d0 100644 --- a/src/Resources/app/administration/package-lock.json +++ b/src/Resources/app/administration/package-lock.json @@ -1,8605 +1,3253 @@ { - "name": "swagmigrationassistant", - "version": "1.0.0", + "name": "swag-migration-assistant", "lockfileVersion": 3, "requires": true, "packages": { "": { - "name": "swagmigrationassistant", - "version": "1.0.0", + "name": "swag-migration-assistant", "license": "MIT", "devDependencies": { - "@babel/core": "^7.24.5", - "@babel/eslint-parser": "^7.24.5", - "@babel/plugin-proposal-class-properties": "^7.18.6", - "@babel/plugin-proposal-decorators": "^7.24.1", - "@babel/plugin-proposal-export-namespace-from": "^7.18.9", - "@babel/plugin-proposal-function-sent": "^7.24.1", - "@babel/plugin-proposal-json-strings": "^7.18.6", - "@babel/plugin-proposal-numeric-separator": "^7.18.6", - "@babel/plugin-proposal-throw-expressions": "^7.24.1", - "@babel/plugin-syntax-dynamic-import": "^7.8.3", - "@babel/plugin-syntax-import-meta": "^7.10.4", - "@babel/plugin-transform-runtime": "^7.24.3", - "@babel/preset-env": "^7.24.5", - "@babel/preset-typescript": "^7.24.1", - "@babel/register": "^7.23.7", - "@shopware-ag/eslint-config-base": "^2.0.0", - "@shopware-ag/stylelint-plugin-meteor": "^1.1.0", - "@typescript-eslint/eslint-plugin": "^7.9.0", - "@typescript-eslint/parser": "^7.9.0", - "babel-jest": "^29.7.0", - "babel-plugin-istanbul": "^6.1.1", - "babel-plugin-module-resolver": "^5.0.2", - "core-js": "^2.6.12", - "eslint": "^8.57.0", - "eslint-import-resolver-webpack": "^0.13.8", - "eslint-plugin-file-progress": "^1.4.0", - "eslint-plugin-filename-rules": "^1.3.1", - "eslint-plugin-html": "^8.1.1", - "eslint-plugin-inclusive-language": "^2.2.1", - "eslint-plugin-jest": "^28.5.0", - "eslint-plugin-plugin-rules": "file:../../../../../../../src/Administration/Resources/app/administration/eslint-rules/plugin-rules", - "eslint-plugin-simple-import-sort": "^12.1.0", - "eslint-plugin-sw-core-rules": "file:../../../../../../../src/Administration/Resources/app/administration/eslint-rules/core-rules", - "eslint-plugin-sw-deprecation-rules": "file:../../../../../../../src/Administration/Resources/app/administration/eslint-rules/deprecation-rules", - "eslint-plugin-sw-test-rules": "file:../../../../../../../src/Administration/Resources/app/administration/eslint-rules/test-rules", - "eslint-plugin-twig-vue": "file:../../../../../../../src/Administration/Resources/app/administration/twigVuePlugin", - "eslint-plugin-vue": "^9.26.0", - "eslint-plugin-vuejs-accessibility": "^2.3.0", - "stylelint": "^16.16.0", - "stylelint-define-config": "^16.15.0" - } - }, - "../../../../../../../src/Administration/Resources/app/administration/eslint-rules/core-rules": { - "name": "sw-core-rules", - "version": "1.0.0", - "dev": true - }, - "../../../../../../../src/Administration/Resources/app/administration/eslint-rules/deprecation-rules": { - "name": "sw-deprecation-rules", - "version": "1.0.0", - "dev": true - }, - "../../../../../../../src/Administration/Resources/app/administration/eslint-rules/plugin-rules": { - "version": "1.0.0", - "dev": true - }, - "../../../../../../../src/Administration/Resources/app/administration/eslint-rules/test-rules": { - "name": "sw-test-rules", - "version": "1.0.0", - "dev": true - }, - "../../../../../../../src/Administration/Resources/app/administration/twigVuePlugin": { - "name": "eslint-plugin-twig-vue", - "version": "0.0.0", - "dev": true, - "license": "ISC", - "dependencies": { - "requireindex": "~1.1.0" - }, - "devDependencies": { - "eslint": "^7.1.0", - "mocha": "^7.2.0" - }, + "@shopware-ag/eslint-config-base": "2.0.0", + "@typescript-eslint/eslint-plugin": "8.21.0", + "@typescript-eslint/parser": "8.21.0", + "eslint": "8.57.1", + "eslint-config-prettier": "9.1.0", + "eslint-plugin-file-progress": "1.5.0", + "eslint-plugin-filename-rules": "1.3.1", + "eslint-plugin-html": "7.1.0", + "eslint-plugin-import": "2.31.0", + "eslint-plugin-inclusive-language": "2.2.1", + "eslint-plugin-vue": "9.32.0", + "eslint-plugin-vuejs-accessibility": "2.4.1", + "prettier": "3.6.2", + "prettier-plugin-multiline-arrays": "3.0.6", + "stylelint": "14.16.1", + "stylelint-config-standard": "26.0.0", + "stylelint-config-standard-scss": "5.0.0", + "stylelint-junit-formatter": "0.2.2", + "typescript": "5.7.3", + "vue": "3.5.22", + "vue-eslint-parser": "9.4.3" + } + }, + "node_modules/@augment-vir/common": { + "version": "28.2.4", + "resolved": "https://registry.npmjs.org/@augment-vir/common/-/common-28.2.4.tgz", + "integrity": "sha512-5Ib0OX7YlxAuFrG+MAoTsz6RlKMcbdMdoNGcEEKH/ezc/ZKMy/IHZ9Z/ZcCHYopZ4ocGXzVY4KUOiJ8+CXXvTA==", + "dev": true, + "license": "MIT", + "dependencies": { + "browser-or-node": "^3.0.0", + "run-time-assertions": "^1.5.1", + "type-fest": "^4.20.1" + } + }, + "node_modules/@augment-vir/common/node_modules/type-fest": { + "version": "4.41.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.41.0.tgz", + "integrity": "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==", + "dev": true, + "license": "(MIT OR CC0-1.0)", "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/@ampproject/remapping": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", - "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", - "dev": true, - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.24" + "node": ">=16" }, - "engines": { - "node": ">=6.0.0" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/@babel/code-frame": { - "version": "7.24.2", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.2.tgz", - "integrity": "sha512-y5+tLQyV8pg3fsiln67BVLD1P13Eg4lh5RW9mF0zUuvLrv9uIQ4MCL+CRT+FTsBlBjcIan6PGsLcBN0m3ClUyQ==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz", + "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/highlight": "^7.24.2", - "picocolors": "^1.0.0" + "@babel/helper-validator-identifier": "^7.27.1", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" }, "engines": { "node": ">=6.9.0" } }, - "node_modules/@babel/compat-data": { - "version": "7.24.4", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.24.4.tgz", - "integrity": "sha512-vg8Gih2MLK+kOkHJp4gBEIkyaIi00jgWot2D9QOmmfLC8jINSOzmCLta6Bvz/JSBCqnegV0L80jhxkol5GWNfQ==", + "node_modules/@babel/helper-string-parser": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", + "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.9.0" } }, - "node_modules/@babel/core": { - "version": "7.24.5", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.24.5.tgz", - "integrity": "sha512-tVQRucExLQ02Boi4vdPp49svNGcfL2GhdTCT9aldhXgCJVAI21EtRfBettiuLUwce/7r6bFdgs6JFkcdTiFttA==", + "node_modules/@babel/helper-validator-identifier": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", + "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", "dev": true, - "dependencies": { - "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.24.2", - "@babel/generator": "^7.24.5", - "@babel/helper-compilation-targets": "^7.23.6", - "@babel/helper-module-transforms": "^7.24.5", - "@babel/helpers": "^7.24.5", - "@babel/parser": "^7.24.5", - "@babel/template": "^7.24.0", - "@babel/traverse": "^7.24.5", - "@babel/types": "^7.24.5", - "convert-source-map": "^2.0.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.2", - "json5": "^2.2.3", - "semver": "^6.3.1" - }, + "license": "MIT", "engines": { "node": ">=6.9.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/babel" - } - }, - "node_modules/@babel/eslint-parser": { - "version": "7.24.5", - "resolved": "https://registry.npmjs.org/@babel/eslint-parser/-/eslint-parser-7.24.5.tgz", - "integrity": "sha512-gsUcqS/fPlgAw1kOtpss7uhY6E9SFFANQ6EFX5GTvzUwaV0+sGaZWk6xq22MOdeT9wfxyokW3ceCUvOiRtZciQ==", - "dev": true, - "dependencies": { - "@nicolo-ribaudo/eslint-scope-5-internals": "5.1.1-v1", - "eslint-visitor-keys": "^2.1.0", - "semver": "^6.3.1" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || >=14.0.0" - }, - "peerDependencies": { - "@babel/core": "^7.11.0", - "eslint": "^7.5.0 || ^8.0.0 || ^9.0.0" } }, - "node_modules/@babel/generator": { - "version": "7.24.5", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.24.5.tgz", - "integrity": "sha512-x32i4hEXvr+iI0NEoEfDKzlemF8AmtOP8CcrRaEcpzysWuoEb1KknpcvMsHKPONoKZiDuItklgWhB18xEhr9PA==", + "node_modules/@babel/parser": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.5.tgz", + "integrity": "sha512-KKBU1VGYR7ORr3At5HAtUQ+TV3SzRCXmA/8OdDZiLDBIZxVyzXuztPjfLd3BV1PRAQGCMWWSHYhL0F8d5uHBDQ==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/types": "^7.24.5", - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.25", - "jsesc": "^2.5.1" + "@babel/types": "^7.28.5" }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-annotate-as-pure": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.22.5.tgz", - "integrity": "sha512-LvBTxu8bQSQkcyKOU+a1btnNFQ1dMAd0R6PyW3arXes06F6QLWLIrd681bxRPIXlrMGR3XYnW9JyML7dP3qgxg==", - "dev": true, - "dependencies": { - "@babel/types": "^7.22.5" + "bin": { + "parser": "bin/babel-parser.js" }, "engines": { - "node": ">=6.9.0" + "node": ">=6.0.0" } }, - "node_modules/@babel/helper-builder-binary-assignment-operator-visitor": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.22.15.tgz", - "integrity": "sha512-QkBXwGgaoC2GtGZRoma6kv7Szfv06khvhFav67ZExau2RaXzy8MpHSMO2PNoP2XtmQphJQRHFfg77Bq731Yizw==", + "node_modules/@babel/types": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.5.tgz", + "integrity": "sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/types": "^7.22.15" + "@babel/helper-string-parser": "^7.27.1", + "@babel/helper-validator-identifier": "^7.28.5" }, "engines": { "node": ">=6.9.0" } }, - "node_modules/@babel/helper-compilation-targets": { - "version": "7.23.6", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.23.6.tgz", - "integrity": "sha512-9JB548GZoQVmzrFgp8o7KxdgkTGm6xs9DW0o/Pim72UDjzr5ObUQ6ZzYPqA+g9OTS2bBQoctLJrky0RDCAWRgQ==", + "node_modules/@csstools/selector-specificity": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@csstools/selector-specificity/-/selector-specificity-2.2.0.tgz", + "integrity": "sha512-+OJ9konv95ClSTOJCmMZqpd5+YGsB2S+x6w3E1oaM8UuR5j8nTNHYSz8c9BEPGDOCMQYIEEGlVPj/VY64iTbGw==", "dev": true, - "dependencies": { - "@babel/compat-data": "^7.23.5", - "@babel/helper-validator-option": "^7.23.5", - "browserslist": "^4.22.2", - "lru-cache": "^5.1.1", - "semver": "^6.3.1" - }, + "license": "CC0-1.0", "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-create-class-features-plugin": { - "version": "7.24.5", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.24.5.tgz", - "integrity": "sha512-uRc4Cv8UQWnE4NXlYTIIdM7wfFkOqlFztcC/gVXDKohKoVB3OyonfelUBaJzSwpBntZ2KYGF/9S7asCHsXwW6g==", - "dev": true, - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.22.5", - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-function-name": "^7.23.0", - "@babel/helper-member-expression-to-functions": "^7.24.5", - "@babel/helper-optimise-call-expression": "^7.22.5", - "@babel/helper-replace-supers": "^7.24.1", - "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5", - "@babel/helper-split-export-declaration": "^7.24.5", - "semver": "^6.3.1" + "node": "^14 || ^16 || >=18" }, - "engines": { - "node": ">=6.9.0" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" }, "peerDependencies": { - "@babel/core": "^7.0.0" + "postcss-selector-parser": "^6.0.10" } }, - "node_modules/@babel/helper-create-regexp-features-plugin": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.22.15.tgz", - "integrity": "sha512-29FkPLFjn4TPEa3RE7GpW+qbE8tlsu3jntNYNfcGsc49LphF1PQIiD+vMZ1z1xVOKt+93khA9tc2JBs3kBjA7w==", + "node_modules/@eslint-community/eslint-utils": { + "version": "4.9.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.0.tgz", + "integrity": "sha512-ayVFHdtZ+hsq1t2Dy24wCmGXGe4q9Gu3smhLYALJrr473ZH27MsnSL+LKUlimp4BWJqMDMLmPpx/Q9R3OAlL4g==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.22.5", - "regexpu-core": "^5.3.1", - "semver": "^6.3.1" + "eslint-visitor-keys": "^3.4.3" }, "engines": { - "node": ">=6.9.0" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/helper-define-polyfill-provider": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.2.tgz", - "integrity": "sha512-LV76g+C502biUK6AyZ3LK10vDpDyCzZnhZFXkH1L75zHPj68+qc8Zfpx2th+gzwA2MzyK+1g/3EPl62yFnVttQ==", - "dev": true, - "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" + "funding": { + "url": "https://opencollective.com/eslint" }, "peerDependencies": { - "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, - "node_modules/@babel/helper-environment-visitor": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz", - "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==", + "node_modules/@eslint-community/regexpp": { + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.2.tgz", + "integrity": "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==", "dev": true, + "license": "MIT", "engines": { - "node": ">=6.9.0" + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" } }, - "node_modules/@babel/helper-function-name": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz", - "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==", + "node_modules/@eslint/eslintrc": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", + "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/template": "^7.22.15", - "@babel/types": "^7.23.0" + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.6.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" }, "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-hoist-variables": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz", - "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==", - "dev": true, - "dependencies": { - "@babel/types": "^7.22.5" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, - "engines": { - "node": ">=6.9.0" + "funding": { + "url": "https://opencollective.com/eslint" } }, - "node_modules/@babel/helper-member-expression-to-functions": { - "version": "7.24.5", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.24.5.tgz", - "integrity": "sha512-4owRteeihKWKamtqg4JmWSsEZU445xpFRXPEwp44HbgbxdWlUV1b4Agg4lkA806Lil5XM/e+FJyS0vj5T6vmcA==", + "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/types": "^7.24.5" - }, - "engines": { - "node": ">=6.9.0" + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" } }, - "node_modules/@babel/helper-module-imports": { - "version": "7.24.3", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.24.3.tgz", - "integrity": "sha512-viKb0F9f2s0BCS22QSF308z/+1YWKV/76mwt61NBzS5izMzDPwdq1pTrzf+Li3npBWX9KdQbkeCt1jSAM7lZqg==", + "node_modules/@eslint/eslintrc/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, + "license": "ISC", "dependencies": { - "@babel/types": "^7.24.0" + "brace-expansion": "^1.1.7" }, "engines": { - "node": ">=6.9.0" + "node": "*" } }, - "node_modules/@babel/helper-module-transforms": { - "version": "7.24.5", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.24.5.tgz", - "integrity": "sha512-9GxeY8c2d2mdQUP1Dye0ks3VDyIMS98kt/llQ2nUId8IsWqTF0l1LkSX0/uP7l7MCDrzXS009Hyhe2gzTiGW8A==", + "node_modules/@eslint/js": { + "version": "8.57.1", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.1.tgz", + "integrity": "sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==", "dev": true, - "dependencies": { - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-module-imports": "^7.24.3", - "@babel/helper-simple-access": "^7.24.5", - "@babel/helper-split-export-declaration": "^7.24.5", - "@babel/helper-validator-identifier": "^7.24.5" - }, + "license": "MIT", "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, - "node_modules/@babel/helper-optimise-call-expression": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.22.5.tgz", - "integrity": "sha512-HBwaojN0xFRx4yIvpwGqxiV2tUfl7401jlok564NgB9EHS1y6QT17FmKWm4ztqjeVdXLuC4fSvHc5ePpQjoTbw==", + "node_modules/@humanwhocodes/config-array": { + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.13.0.tgz", + "integrity": "sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==", + "deprecated": "Use @eslint/config-array instead", "dev": true, + "license": "Apache-2.0", "dependencies": { - "@babel/types": "^7.22.5" + "@humanwhocodes/object-schema": "^2.0.3", + "debug": "^4.3.1", + "minimatch": "^3.0.5" }, "engines": { - "node": ">=6.9.0" + "node": ">=10.10.0" } }, - "node_modules/@babel/helper-plugin-utils": { - "version": "7.24.5", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.5.tgz", - "integrity": "sha512-xjNLDopRzW2o6ba0gKbkZq5YWEBaK3PCyTOY1K2P/O07LGMhMqlMXPxwN4S5/RhWuCobT8z0jrlKGlYmeR1OhQ==", + "node_modules/@humanwhocodes/config-array/node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", "dev": true, - "engines": { - "node": ">=6.9.0" + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" } }, - "node_modules/@babel/helper-remap-async-to-generator": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.22.20.tgz", - "integrity": "sha512-pBGyV4uBqOns+0UvhsTO8qgl8hO89PmiDYv+/COyp1aeMcmfrfruz+/nCMFiYyFF/Knn0yfrC85ZzNFjembFTw==", + "node_modules/@humanwhocodes/config-array/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, + "license": "ISC", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.22.5", - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-wrap-function": "^7.22.20" + "brace-expansion": "^1.1.7" }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" + "node": "*" } }, - "node_modules/@babel/helper-replace-supers": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.24.1.tgz", - "integrity": "sha512-QCR1UqC9BzG5vZl8BMicmZ28RuUBnHhAMddD8yHFHDRH9lLTZ9uUPehX8ctVPT8l0TKblJidqcgUUKGVrePleQ==", + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", "dev": true, - "dependencies": { - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-member-expression-to-functions": "^7.23.0", - "@babel/helper-optimise-call-expression": "^7.22.5" - }, + "license": "Apache-2.0", "engines": { - "node": ">=6.9.0" + "node": ">=12.22" }, - "peerDependencies": { - "@babel/core": "^7.0.0" + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" } }, - "node_modules/@babel/helper-simple-access": { - "version": "7.24.5", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.24.5.tgz", - "integrity": "sha512-uH3Hmf5q5n7n8mz7arjUlDOCbttY/DW4DYhE6FUsjKJ/oYC1kQQUvwEQWxRwUpX9qQKRXeqLwWxrqilMrf32sQ==", + "node_modules/@humanwhocodes/object-schema": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", + "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", + "deprecated": "Use @eslint/object-schema instead", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "dev": true, + "license": "MIT" + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/types": "^7.24.5" + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" }, "engines": { - "node": ">=6.9.0" + "node": ">= 8" } }, - "node_modules/@babel/helper-skip-transparent-expression-wrappers": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.22.5.tgz", - "integrity": "sha512-tK14r66JZKiC43p8Ki33yLBVJKlQDFoA8GYN67lWCDCqoL6EMMSuM9b+Iff2jHaM/RRFYl7K+iiru7hbRqNx8Q==", + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", "dev": true, - "dependencies": { - "@babel/types": "^7.22.5" - }, + "license": "MIT", "engines": { - "node": ">=6.9.0" + "node": ">= 8" } }, - "node_modules/@babel/helper-split-export-declaration": { - "version": "7.24.5", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.24.5.tgz", - "integrity": "sha512-5CHncttXohrHk8GWOFCcCl4oRD9fKosWlIRgWm4ql9VYioKm52Mk2xsmoohvm7f3JoiLSM5ZgJuRaf5QZZYd3Q==", + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/types": "^7.24.5" + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" }, "engines": { - "node": ">=6.9.0" + "node": ">= 8" } }, - "node_modules/@babel/helper-string-parser": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.1.tgz", - "integrity": "sha512-2ofRCjnnA9y+wk8b9IAREroeUP02KHp431N2mhKniy2yKIDKpbrHv9eXwm8cBeWQYcJmzv5qKCu65P47eCF7CQ==", + "node_modules/@rtsao/scc": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@rtsao/scc/-/scc-1.1.0.tgz", + "integrity": "sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==", "dev": true, - "engines": { - "node": ">=6.9.0" - } + "license": "MIT" }, - "node_modules/@babel/helper-validator-identifier": { - "version": "7.24.5", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.5.tgz", - "integrity": "sha512-3q93SSKX2TWCG30M2G2kwaKeTYgEUp5Snjuj8qm729SObL6nbtUldAi37qbxkD5gg3xnBio+f9nqpSepGZMvxA==", + "node_modules/@shopware-ag/eslint-config-base": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@shopware-ag/eslint-config-base/-/eslint-config-base-2.0.0.tgz", + "integrity": "sha512-G7VOfkg9SsybDfCohUB+YRcn/yaTzxQfNLfNdmvE03BK7kh0f2edwUu64FfQKMcRzVmL8lvu/sl4oErTJsNsQA==", "dev": true, - "engines": { - "node": ">=6.9.0" + "license": "MIT", + "dependencies": { + "eslint": "^8.29.0", + "eslint-config-airbnb-base": "^15.0.0", + "eslint-plugin-import": "2.26.0" } }, - "node_modules/@babel/helper-validator-option": { - "version": "7.23.5", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.23.5.tgz", - "integrity": "sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw==", + "node_modules/@shopware-ag/eslint-config-base/node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", "dev": true, - "engines": { - "node": ">=6.9.0" + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" } }, - "node_modules/@babel/helper-wrap-function": { - "version": "7.24.5", - "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.24.5.tgz", - "integrity": "sha512-/xxzuNvgRl4/HLNKvnFwdhdgN3cpLxgLROeLDl83Yx0AJ1SGvq1ak0OszTOjDfiB8Vx03eJbeDWh9r+jCCWttw==", + "node_modules/@shopware-ag/eslint-config-base/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-function-name": "^7.23.0", - "@babel/template": "^7.24.0", - "@babel/types": "^7.24.5" - }, - "engines": { - "node": ">=6.9.0" + "ms": "2.0.0" } }, - "node_modules/@babel/helpers": { - "version": "7.24.5", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.24.5.tgz", - "integrity": "sha512-CiQmBMMpMQHwM5m01YnrM6imUG1ebgYJ+fAIW4FZe6m4qHTPaRHti+R8cggAwkdz4oXhtO4/K9JWlh+8hIfR2Q==", + "node_modules/@shopware-ag/eslint-config-base/node_modules/doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", "dev": true, + "license": "Apache-2.0", "dependencies": { - "@babel/template": "^7.24.0", - "@babel/traverse": "^7.24.5", - "@babel/types": "^7.24.5" + "esutils": "^2.0.2" }, "engines": { - "node": ">=6.9.0" + "node": ">=0.10.0" } }, - "node_modules/@babel/highlight": { - "version": "7.24.5", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.5.tgz", - "integrity": "sha512-8lLmua6AVh/8SLJRRVD6V8p73Hir9w5mJrhE+IPpILG31KKlI9iz5zmBYKcWPS59qSfgP9RaSBQSHHE81WKuEw==", - "dev": true, - "dependencies": { - "@babel/helper-validator-identifier": "^7.24.5", - "chalk": "^2.4.2", - "js-tokens": "^4.0.0", - "picocolors": "^1.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/parser": { - "version": "7.24.5", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.5.tgz", - "integrity": "sha512-EOv5IK8arwh3LI47dz1b0tKUb/1uhHAnHJOrjgtQMIpu1uXd9mlFrJg9IUgGUgZ41Ch0K8REPTYpO7B76b4vJg==", - "dev": true, - "bin": { - "parser": "bin/babel-parser.js" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@babel/plugin-bugfix-firefox-class-in-computed-class-key": { - "version": "7.24.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.24.5.tgz", - "integrity": "sha512-LdXRi1wEMTrHVR4Zc9F8OewC3vdm5h4QB6L71zy6StmYeqGi1b3ttIO8UC+BfZKcH9jdr4aI249rBkm+3+YvHw==", + "node_modules/@shopware-ag/eslint-config-base/node_modules/eslint-plugin-import": { + "version": "2.26.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.26.0.tgz", + "integrity": "sha512-hYfi3FXaM8WPLf4S1cikh/r4IxnO6zrhZbEGz2b660EJRbuxgpDS5gkCuYgGWg2xxh2rBuIr4Pvhve/7c31koA==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-plugin-utils": "^7.24.5" + "array-includes": "^3.1.4", + "array.prototype.flat": "^1.2.5", + "debug": "^2.6.9", + "doctrine": "^2.1.0", + "eslint-import-resolver-node": "^0.3.6", + "eslint-module-utils": "^2.7.3", + "has": "^1.0.3", + "is-core-module": "^2.8.1", + "is-glob": "^4.0.3", + "minimatch": "^3.1.2", + "object.values": "^1.1.5", + "resolve": "^1.22.0", + "tsconfig-paths": "^3.14.1" }, "engines": { - "node": ">=6.9.0" + "node": ">=4" }, "peerDependencies": { - "@babel/core": "^7.0.0" + "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8" } }, - "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.24.1.tgz", - "integrity": "sha512-y4HqEnkelJIOQGd+3g1bTeKsA5c6qM7eOn7VggGVbBc0y8MLSKHacwcIE2PplNlQSj0PqS9rrXL/nkPVK+kUNg==", + "node_modules/@shopware-ag/eslint-config-base/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, + "license": "ISC", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.0" + "brace-expansion": "^1.1.7" }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" + "node": "*" } }, - "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.24.1.tgz", - "integrity": "sha512-Hj791Ii4ci8HqnaKHAlLNs+zaLXb0EzSDhiAWp5VNlyvCNymYfacs64pxTxbH1znW/NcArSmwpmG9IKE/TUVVQ==", + "node_modules/@shopware-ag/eslint-config-base/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/json5": { + "version": "0.0.29", + "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", + "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-hov8bUuiLiyFPGyFPE1lwWhmzYbirOXQNNo40+y3zow8aFVTeyn3VWL0VFFfdNddA8S4Vf0Tc062rzyNr7Paag==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/normalize-package-data": { + "version": "2.4.4", + "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.4.tgz", + "integrity": "sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/parse-json": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.2.tgz", + "integrity": "sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "8.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.21.0.tgz", + "integrity": "sha512-eTH+UOR4I7WbdQnG4Z48ebIA6Bgi7WO8HvFEneeYBxG8qCOYgTOFPSg6ek9ITIDvGjDQzWHcoWHCDO2biByNzA==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.0", - "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5", - "@babel/plugin-transform-optional-chaining": "^7.24.1" + "@eslint-community/regexpp": "^4.10.0", + "@typescript-eslint/scope-manager": "8.21.0", + "@typescript-eslint/type-utils": "8.21.0", + "@typescript-eslint/utils": "8.21.0", + "@typescript-eslint/visitor-keys": "8.21.0", + "graphemer": "^1.4.0", + "ignore": "^5.3.1", + "natural-compare": "^1.4.0", + "ts-api-utils": "^2.0.0" }, "engines": { - "node": ">=6.9.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "@babel/core": "^7.13.0" + "@typescript-eslint/parser": "^8.0.0 || ^8.0.0-alpha.0", + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.8.0" } }, - "node_modules/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.24.1.tgz", - "integrity": "sha512-m9m/fXsXLiHfwdgydIFnpk+7jlVbnvlK5B2EKiPdLUb6WX654ZaaEWJUjk8TftRbZpK0XibovlLWX4KIZhV6jw==", + "node_modules/@typescript-eslint/parser": { + "version": "8.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.21.0.tgz", + "integrity": "sha512-Wy+/sdEH9kI3w9civgACwabHbKl+qIOu0uFZ9IMKzX3Jpv9og0ZBJrZExGrPpFAY7rWsXuxs5e7CPPP17A4eYA==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-plugin-utils": "^7.24.0" + "@typescript-eslint/scope-manager": "8.21.0", + "@typescript-eslint/types": "8.21.0", + "@typescript-eslint/typescript-estree": "8.21.0", + "@typescript-eslint/visitor-keys": "8.21.0", + "debug": "^4.3.4" }, "engines": { - "node": ">=6.9.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "@babel/core": "^7.0.0" + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.8.0" } }, - "node_modules/@babel/plugin-proposal-class-properties": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.18.6.tgz", - "integrity": "sha512-cumfXOF0+nzZrrN8Rf0t7M+tF6sZc7vhQwYQck9q1/5w2OExlD+b4v4RpMJFaV1Z7WcDRgO6FqvxqxGlwo+RHQ==", - "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-class-properties instead.", + "node_modules/@typescript-eslint/scope-manager": { + "version": "8.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.21.0.tgz", + "integrity": "sha512-G3IBKz0/0IPfdeGRMbp+4rbjfSSdnGkXsM/pFZA8zM9t9klXDnB/YnKOBQ0GoPmoROa4bCq2NeHgJa5ydsQ4mA==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" + "@typescript-eslint/types": "8.21.0", + "@typescript-eslint/visitor-keys": "8.21.0" }, "engines": { - "node": ">=6.9.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@babel/plugin-proposal-decorators": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.24.1.tgz", - "integrity": "sha512-zPEvzFijn+hRvJuX2Vu3KbEBN39LN3f7tW3MQO2LsIs57B26KU+kUc82BdAktS1VCM6libzh45eKGI65lg0cpA==", + "node_modules/@typescript-eslint/type-utils": { + "version": "8.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.21.0.tgz", + "integrity": "sha512-95OsL6J2BtzoBxHicoXHxgk3z+9P3BEcQTpBKriqiYzLKnM2DeSqs+sndMKdamU8FosiadQFT3D+BSL9EKnAJQ==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.24.1", - "@babel/helper-plugin-utils": "^7.24.0", - "@babel/plugin-syntax-decorators": "^7.24.1" + "@typescript-eslint/typescript-estree": "8.21.0", + "@typescript-eslint/utils": "8.21.0", + "debug": "^4.3.4", + "ts-api-utils": "^2.0.0" }, "engines": { - "node": ">=6.9.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.8.0" } }, - "node_modules/@babel/plugin-proposal-export-namespace-from": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.18.9.tgz", - "integrity": "sha512-k1NtHyOMvlDDFeb9G5PhUXuGj8m/wiwojgQVEhJ/fsVsMCpLyOP4h0uGEjYJKrRI+EVPlb5Jk+Gt9P97lOGwtA==", - "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-export-namespace-from instead.", + "node_modules/@typescript-eslint/types": { + "version": "8.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.21.0.tgz", + "integrity": "sha512-PAL6LUuQwotLW2a8VsySDBwYMm129vFm4tMVlylzdoTybTHaAi0oBp7Ac6LhSrHHOdLM3efH+nAR6hAWoMF89A==", "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.9", - "@babel/plugin-syntax-export-namespace-from": "^7.8.3" - }, + "license": "MIT", "engines": { - "node": ">=6.9.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@babel/plugin-proposal-function-sent": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-function-sent/-/plugin-proposal-function-sent-7.24.1.tgz", - "integrity": "sha512-GxHpB7jATDZWYEuYkR5jv5aiHbwkmbvk3fJP5G2Dvl7va+kewfbYxpnU1BadIHd3kXlLPQj4CKbLKoWxX4nTtA==", + "node_modules/@typescript-eslint/typescript-estree": { + "version": "8.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.21.0.tgz", + "integrity": "sha512-x+aeKh/AjAArSauz0GiQZsjT8ciadNMHdkUSwBB9Z6PrKc/4knM4g3UfHml6oDJmKC88a6//cdxnO/+P2LkMcg==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.0", - "@babel/helper-wrap-function": "^7.22.20", - "@babel/plugin-syntax-function-sent": "^7.24.1" + "@typescript-eslint/types": "8.21.0", + "@typescript-eslint/visitor-keys": "8.21.0", + "debug": "^4.3.4", + "fast-glob": "^3.3.2", + "is-glob": "^4.0.3", + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^2.0.0" }, "engines": { - "node": ">=6.9.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "typescript": ">=4.8.4 <5.8.0" } }, - "node_modules/@babel/plugin-proposal-json-strings": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.18.6.tgz", - "integrity": "sha512-lr1peyn9kOdbYc0xr0OdHTZ5FMqS6Di+H0Fz2I/JwMzGmzJETNeOFq2pBySw6X/KFL5EWDjlJuMsUGRFb8fQgQ==", - "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-json-strings instead.", + "node_modules/@typescript-eslint/utils": { + "version": "8.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.21.0.tgz", + "integrity": "sha512-xcXBfcq0Kaxgj7dwejMbFyq7IOHgpNMtVuDveK7w3ZGwG9owKzhALVwKpTF2yrZmEwl9SWdetf3fxNzJQaVuxw==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/plugin-syntax-json-strings": "^7.8.3" + "@eslint-community/eslint-utils": "^4.4.0", + "@typescript-eslint/scope-manager": "8.21.0", + "@typescript-eslint/types": "8.21.0", + "@typescript-eslint/typescript-estree": "8.21.0" }, "engines": { - "node": ">=6.9.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.8.0" } }, - "node_modules/@babel/plugin-proposal-numeric-separator": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.18.6.tgz", - "integrity": "sha512-ozlZFogPqoLm8WBr5Z8UckIoE4YQ5KESVcNudyXOR8uqIkliTEgJ3RoketfG6pmzLdeZF0H/wjE9/cCEitBl7Q==", - "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-numeric-separator instead.", + "node_modules/@typescript-eslint/visitor-keys": { + "version": "8.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.21.0.tgz", + "integrity": "sha512-BkLMNpdV6prozk8LlyK/SOoWLmUFi+ZD+pcqti9ILCbVvHGk1ui1g4jJOc2WDLaeExz2qWwojxlPce5PljcT3w==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/plugin-syntax-numeric-separator": "^7.10.4" + "@typescript-eslint/types": "8.21.0", + "eslint-visitor-keys": "^4.2.0" }, "engines": { - "node": ">=6.9.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@babel/plugin-proposal-private-property-in-object": { - "version": "7.21.0-placeholder-for-preset-env.2", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz", - "integrity": "sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==", + "node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", "dev": true, + "license": "Apache-2.0", "engines": { - "node": ">=6.9.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "funding": { + "url": "https://opencollective.com/eslint" } }, - "node_modules/@babel/plugin-proposal-throw-expressions": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-throw-expressions/-/plugin-proposal-throw-expressions-7.24.1.tgz", - "integrity": "sha512-wiae/VkKNX1WuM+wXIeAZY1cvbVKJJIf92eA23s2ufpp4w+vOlp+/4T3yfxN6nzN+hIwT15AsdwujAelIqNW+w==", + "node_modules/@ungap/structured-clone": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.0.tgz", + "integrity": "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==", "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.0", - "@babel/plugin-syntax-throw-expressions": "^7.24.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } + "license": "ISC" }, - "node_modules/@babel/plugin-syntax-async-generators": { - "version": "7.8.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", - "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", + "node_modules/@vue/compiler-core": { + "version": "3.5.22", + "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.22.tgz", + "integrity": "sha512-jQ0pFPmZwTEiRNSb+i9Ow/I/cHv2tXYqsnHKKyCQ08irI2kdF5qmYedmF8si8mA7zepUFmJ2hqzS8CQmNOWOkQ==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@babel/parser": "^7.28.4", + "@vue/shared": "3.5.22", + "entities": "^4.5.0", + "estree-walker": "^2.0.2", + "source-map-js": "^1.2.1" } }, - "node_modules/@babel/plugin-syntax-bigint": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz", - "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==", + "node_modules/@vue/compiler-dom": { + "version": "3.5.22", + "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.22.tgz", + "integrity": "sha512-W8RknzUM1BLkypvdz10OVsGxnMAuSIZs9Wdx1vzA3mL5fNMN15rhrSCLiTm6blWeACwUwizzPVqGJgOGBEN/hA==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@vue/compiler-core": "3.5.22", + "@vue/shared": "3.5.22" } }, - "node_modules/@babel/plugin-syntax-class-properties": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", - "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", + "node_modules/@vue/compiler-sfc": { + "version": "3.5.22", + "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.22.tgz", + "integrity": "sha512-tbTR1zKGce4Lj+JLzFXDq36K4vcSZbJ1RBu8FxcDv1IGRz//Dh2EBqksyGVypz3kXpshIfWKGOCcqpSbyGWRJQ==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.12.13" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@babel/parser": "^7.28.4", + "@vue/compiler-core": "3.5.22", + "@vue/compiler-dom": "3.5.22", + "@vue/compiler-ssr": "3.5.22", + "@vue/shared": "3.5.22", + "estree-walker": "^2.0.2", + "magic-string": "^0.30.19", + "postcss": "^8.5.6", + "source-map-js": "^1.2.1" } }, - "node_modules/@babel/plugin-syntax-class-static-block": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", - "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", + "node_modules/@vue/compiler-ssr": { + "version": "3.5.22", + "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.22.tgz", + "integrity": "sha512-GdgyLvg4R+7T8Nk2Mlighx7XGxq/fJf9jaVofc3IL0EPesTE86cP/8DD1lT3h1JeZr2ySBvyqKQJgbS54IX1Ww==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@vue/compiler-dom": "3.5.22", + "@vue/shared": "3.5.22" } }, - "node_modules/@babel/plugin-syntax-decorators": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-decorators/-/plugin-syntax-decorators-7.24.1.tgz", - "integrity": "sha512-05RJdO/cCrtVWuAaSn1tS3bH8jbsJa/Y1uD186u6J4C/1mnHFxseeuWpsqr9anvo7TUulev7tm7GDwRV+VuhDw==", + "node_modules/@vue/reactivity": { + "version": "3.5.22", + "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.5.22.tgz", + "integrity": "sha512-f2Wux4v/Z2pqc9+4SmgZC1p73Z53fyD90NFWXiX9AKVnVBEvLFOWCEgJD3GdGnlxPZt01PSlfmLqbLYzY/Fw4A==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@vue/shared": "3.5.22" } }, - "node_modules/@babel/plugin-syntax-dynamic-import": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz", - "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==", + "node_modules/@vue/runtime-core": { + "version": "3.5.22", + "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.5.22.tgz", + "integrity": "sha512-EHo4W/eiYeAzRTN5PCextDUZ0dMs9I8mQ2Fy+OkzvRPUYQEyK9yAjbasrMCXbLNhF7P0OUyivLjIy0yc6VrLJQ==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@vue/reactivity": "3.5.22", + "@vue/shared": "3.5.22" } }, - "node_modules/@babel/plugin-syntax-export-namespace-from": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz", - "integrity": "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==", + "node_modules/@vue/runtime-dom": { + "version": "3.5.22", + "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.5.22.tgz", + "integrity": "sha512-Av60jsryAkI023PlN7LsqrfPvwfxOd2yAwtReCjeuugTJTkgrksYJJstg1e12qle0NarkfhfFu1ox2D+cQotww==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.8.3" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@vue/reactivity": "3.5.22", + "@vue/runtime-core": "3.5.22", + "@vue/shared": "3.5.22", + "csstype": "^3.1.3" } }, - "node_modules/@babel/plugin-syntax-function-sent": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-function-sent/-/plugin-syntax-function-sent-7.24.1.tgz", - "integrity": "sha512-aVwkxqagsGCI8vtuyMI+LnZ2SWtGP4+v9T/T88j2MwKRsGYzc9FAaEzsNMu1Htu6SsHPcfwQ7uZ7pYPGrVmG+g==", + "node_modules/@vue/server-renderer": { + "version": "3.5.22", + "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.5.22.tgz", + "integrity": "sha512-gXjo+ao0oHYTSswF+a3KRHZ1WszxIqO7u6XwNHqcqb9JfyIL/pbWrrh/xLv7jeDqla9u+LK7yfZKHih1e1RKAQ==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.0" - }, - "engines": { - "node": ">=6.9.0" + "@vue/compiler-ssr": "3.5.22", + "@vue/shared": "3.5.22" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "vue": "3.5.22" } }, - "node_modules/@babel/plugin-syntax-import-assertions": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.24.1.tgz", - "integrity": "sha512-IuwnI5XnuF189t91XbxmXeCDz3qs6iDRO7GJ++wcfgeXNs/8FmIlKcpDSXNVyuLQxlwvskmI3Ct73wUODkJBlQ==", + "node_modules/@vue/shared": { + "version": "3.5.22", + "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.22.tgz", + "integrity": "sha512-F4yc6palwq3TT0u+FYf0Ns4Tfl9GRFURDN2gWG7L1ecIaS/4fCIuFOjMTnCyjsu/OK6vaDKLCrGAa+KvvH+h4w==", "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } + "license": "MIT" }, - "node_modules/@babel/plugin-syntax-import-attributes": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.24.1.tgz", - "integrity": "sha512-zhQTMH0X2nVLnb04tz+s7AMuasX8U0FnpE+nHTOhSOINjWMnopoZTxtIKsd45n4GQ/HIZLyfIpoul8e2m0DnRA==", + "node_modules/acorn": { + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", + "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.0" + "license": "MIT", + "bin": { + "acorn": "bin/acorn" }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=0.4.0" } }, - "node_modules/@babel/plugin-syntax-import-meta": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", - "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" - }, + "license": "MIT", "peerDependencies": { - "@babel/core": "^7.0.0-0" + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, - "node_modules/@babel/plugin-syntax-json-strings": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", - "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" } }, - "node_modules/@babel/plugin-syntax-jsx": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.24.1.tgz", - "integrity": "sha512-2eCtxZXf+kbkMIsXS4poTvT4Yu5rXiRa+9xGVT56raghjmBTKMpFNc9R4IDiB4emao9eO22Ox7CxuJG7BgExqA==", + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.0" - }, + "license": "MIT", "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=8" } }, - "node_modules/@babel/plugin-syntax-logical-assignment-operators": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", - "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" + "color-convert": "^2.0.1" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", - "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" + "engines": { + "node": ">=8" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/@babel/plugin-syntax-numeric-separator": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", - "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } + "license": "Python-2.0" }, - "node_modules/@babel/plugin-syntax-object-rest-spread": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", - "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", + "node_modules/aria-query": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.2.tgz", + "integrity": "sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==", "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "license": "Apache-2.0", + "engines": { + "node": ">= 0.4" } }, - "node_modules/@babel/plugin-syntax-optional-catch-binding": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", - "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", + "node_modules/array-buffer-byte-length": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.2.tgz", + "integrity": "sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" + "call-bound": "^1.0.3", + "is-array-buffer": "^3.0.5" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-optional-chaining": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", - "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" + "engines": { + "node": ">= 0.4" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/@babel/plugin-syntax-private-property-in-object": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", - "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", + "node_modules/array-includes": { + "version": "3.1.9", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.9.tgz", + "integrity": "sha512-FmeCCAenzH0KH381SPT5FZmiA/TmpndpcaShhfgEN9eCVjnFBqq3l1xrI42y8+PPLI6hypzou4GXw00WHmPBLQ==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "define-properties": "^1.2.1", + "es-abstract": "^1.24.0", + "es-object-atoms": "^1.1.1", + "get-intrinsic": "^1.3.0", + "is-string": "^1.1.1", + "math-intrinsics": "^1.1.0" }, "engines": { - "node": ">=6.9.0" + "node": ">= 0.4" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/@babel/plugin-syntax-throw-expressions": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-throw-expressions/-/plugin-syntax-throw-expressions-7.24.1.tgz", - "integrity": "sha512-o4dN/9/hUAC6RuX1QZDlauBG2nmSmUMk0K7/IOIFxjM8V16FS1JTHHiBWqGkkIjK4myeHucJbBHurqjtWFAdsw==", + "node_modules/array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.0" - }, + "license": "MIT", "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=8" } }, - "node_modules/@babel/plugin-syntax-top-level-await": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", - "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", + "node_modules/array.prototype.findlastindex": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.6.tgz", + "integrity": "sha512-F/TKATkzseUExPlfvmwQKGITM3DGTK+vkAsCZoDc5daVygbJBnjEUCbgkAvVFsgfXfX4YIqZ/27G3k3tdXrTxQ==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.9", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "es-shim-unscopables": "^1.1.0" }, "engines": { - "node": ">=6.9.0" + "node": ">= 0.4" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/@babel/plugin-syntax-typescript": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.24.1.tgz", - "integrity": "sha512-Yhnmvy5HZEnHUty6i++gcfH1/l68AHnItFHnaCv6hn9dNh0hQvvQJsxpi4BMBFN5DLeHBuucT/0DgzXif/OyRw==", + "node_modules/array.prototype.flat": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.3.tgz", + "integrity": "sha512-rwG/ja1neyLqCuGZ5YYrznA62D4mZXg0i1cIskIUKSiqF3Cje9/wXAls9B9s1Wa2fomMsIv8czB8jZcPmxCXFg==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.0" + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-shim-unscopables": "^1.0.2" }, "engines": { - "node": ">=6.9.0" + "node": ">= 0.4" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/@babel/plugin-syntax-unicode-sets-regex": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-unicode-sets-regex/-/plugin-syntax-unicode-sets-regex-7.18.6.tgz", - "integrity": "sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==", + "node_modules/array.prototype.flatmap": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.3.tgz", + "integrity": "sha512-Y7Wt51eKJSyi80hFrJCePGGNo5ktJCslFuboqJsbf57CCPcm5zztluPlc4/aD8sWsKvlwatezpV4U1efk8kpjg==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-shim-unscopables": "^1.0.2" }, "engines": { - "node": ">=6.9.0" + "node": ">= 0.4" }, - "peerDependencies": { - "@babel/core": "^7.0.0" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/@babel/plugin-transform-arrow-functions": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.24.1.tgz", - "integrity": "sha512-ngT/3NkRhsaep9ck9uj2Xhv9+xB1zShY3tM3g6om4xxCELwCDN4g4Aq5dRn48+0hasAql7s2hdBOysCfNpr4fw==", + "node_modules/arraybuffer.prototype.slice": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.4.tgz", + "integrity": "sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.0" + "array-buffer-byte-length": "^1.0.1", + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "is-array-buffer": "^3.0.4" }, "engines": { - "node": ">=6.9.0" + "node": ">= 0.4" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/@babel/plugin-transform-async-generator-functions": { - "version": "7.24.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.24.3.tgz", - "integrity": "sha512-Qe26CMYVjpQxJ8zxM1340JFNjZaF+ISWpr1Kt/jGo+ZTUzKkfw/pphEWbRCb+lmSM6k/TOgfYLvmbHkUQ0asIg==", + "node_modules/arrify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", + "integrity": "sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==", "dev": true, - "dependencies": { - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-plugin-utils": "^7.24.0", - "@babel/helper-remap-async-to-generator": "^7.22.20", - "@babel/plugin-syntax-async-generators": "^7.8.4" - }, + "license": "MIT", "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=0.10.0" } }, - "node_modules/@babel/plugin-transform-async-to-generator": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.24.1.tgz", - "integrity": "sha512-AawPptitRXp1y0n4ilKcGbRYWfbbzFWz2NqNu7dacYDtFtz0CMjG64b3LQsb3KIgnf4/obcUL78hfaOS7iCUfw==", + "node_modules/astral-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", + "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", "dev": true, - "dependencies": { - "@babel/helper-module-imports": "^7.24.1", - "@babel/helper-plugin-utils": "^7.24.0", - "@babel/helper-remap-async-to-generator": "^7.22.20" - }, + "license": "MIT", "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=8" } }, - "node_modules/@babel/plugin-transform-block-scoped-functions": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.24.1.tgz", - "integrity": "sha512-TWWC18OShZutrv9C6mye1xwtam+uNi2bnTOCBUd5sZxyHOiWbU6ztSROofIMrK84uweEZC219POICK/sTYwfgg==", + "node_modules/async-function": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/async-function/-/async-function-1.0.0.tgz", + "integrity": "sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==", "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.0" - }, + "license": "MIT", "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">= 0.4" } }, - "node_modules/@babel/plugin-transform-block-scoping": { - "version": "7.24.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.24.5.tgz", - "integrity": "sha512-sMfBc3OxghjC95BkYrYocHL3NaOplrcaunblzwXhGmlPwpmfsxr4vK+mBBt49r+S240vahmv+kUxkeKgs+haCw==", + "node_modules/available-typed-arrays": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", + "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.5" + "possible-typed-array-names": "^1.0.0" }, "engines": { - "node": ">=6.9.0" + "node": ">= 0.4" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/@babel/plugin-transform-class-properties": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.24.1.tgz", - "integrity": "sha512-OMLCXi0NqvJfORTaPQBwqLXHhb93wkBKZ4aNwMl6WtehO7ar+cmp+89iPEQPqxAnxsOKTaMcs3POz3rKayJ72g==", + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "dev": true, - "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.24.1", - "@babel/helper-plugin-utils": "^7.24.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } + "license": "MIT" }, - "node_modules/@babel/plugin-transform-class-static-block": { - "version": "7.24.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.24.4.tgz", - "integrity": "sha512-B8q7Pz870Hz/q9UgP8InNpY01CSLDSCyqX7zcRuv3FcPl87A2G17lASroHWaCtbdIcbYzOZ7kWmXFKbijMSmFg==", + "node_modules/boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", "dev": true, - "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.24.4", - "@babel/helper-plugin-utils": "^7.24.0", - "@babel/plugin-syntax-class-static-block": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.12.0" - } + "license": "ISC" }, - "node_modules/@babel/plugin-transform-classes": { - "version": "7.24.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.24.5.tgz", - "integrity": "sha512-gWkLP25DFj2dwe9Ck8uwMOpko4YsqyfZJrOmqqcegeDYEbp7rmn4U6UQZNj08UF6MaX39XenSpKRCvpDRBtZ7Q==", + "node_modules/brace-expansion": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.22.5", - "@babel/helper-compilation-targets": "^7.23.6", - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-function-name": "^7.23.0", - "@babel/helper-plugin-utils": "^7.24.5", - "@babel/helper-replace-supers": "^7.24.1", - "@babel/helper-split-export-declaration": "^7.24.5", - "globals": "^11.1.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "balanced-match": "^1.0.0" } }, - "node_modules/@babel/plugin-transform-computed-properties": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.24.1.tgz", - "integrity": "sha512-5pJGVIUfJpOS+pAqBQd+QMaTD2vCL/HcePooON6pDpHgRp4gNRmzyHTPIkXntwKsq3ayUFVfJaIKPw2pOkOcTw==", + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.0", - "@babel/template": "^7.24.0" + "fill-range": "^7.1.1" }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=8" } }, - "node_modules/@babel/plugin-transform-destructuring": { - "version": "7.24.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.24.5.tgz", - "integrity": "sha512-SZuuLyfxvsm+Ah57I/i1HVjveBENYK9ue8MJ7qkc7ndoNjqquJiElzA7f5yaAXjyW2hKojosOTAQQRX50bPSVg==", + "node_modules/browser-or-node": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/browser-or-node/-/browser-or-node-3.0.0.tgz", + "integrity": "sha512-iczIdVJzGEYhP5DqQxYM9Hh7Ztpqqi+CXZpSmX8ALFs9ecXkQIeqRyM6TfxEfMVpwhl3dSuDvxdzzo9sUOIVBQ==", "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } + "license": "MIT" }, - "node_modules/@babel/plugin-transform-dotall-regex": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.24.1.tgz", - "integrity": "sha512-p7uUxgSoZwZ2lPNMzUkqCts3xlp8n+o05ikjy7gbtFJSt9gdU88jAmtfmOxHM14noQXBxfgzf2yRWECiNVhTCw==", + "node_modules/call-bind": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz", + "integrity": "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.22.15", - "@babel/helper-plugin-utils": "^7.24.0" + "call-bind-apply-helpers": "^1.0.0", + "es-define-property": "^1.0.0", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.2" }, "engines": { - "node": ">=6.9.0" + "node": ">= 0.4" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/@babel/plugin-transform-duplicate-keys": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.24.1.tgz", - "integrity": "sha512-msyzuUnvsjsaSaocV6L7ErfNsa5nDWL1XKNnDePLgmz+WdU4w/J8+AxBMrWfi9m4IxfL5sZQKUPQKDQeeAT6lA==", + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.0" + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">= 0.4" } }, - "node_modules/@babel/plugin-transform-dynamic-import": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.24.1.tgz", - "integrity": "sha512-av2gdSTyXcJVdI+8aFZsCAtR29xJt0S5tas+Ef8NvBNmD1a+N/3ecMLeMBgfcK+xzsjdLDT6oHt+DFPyeqUbDA==", + "node_modules/call-bound": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.0", - "@babel/plugin-syntax-dynamic-import": "^7.8.3" + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" }, "engines": { - "node": ">=6.9.0" + "node": ">= 0.4" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/@babel/plugin-transform-exponentiation-operator": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.24.1.tgz", - "integrity": "sha512-U1yX13dVBSwS23DEAqU+Z/PkwE9/m7QQy8Y9/+Tdb8UWYaGNDYwTLi19wqIAiROr8sXVum9A/rtiH5H0boUcTw==", + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", "dev": true, - "dependencies": { - "@babel/helper-builder-binary-assignment-operator-visitor": "^7.22.15", - "@babel/helper-plugin-utils": "^7.24.0" - }, + "license": "MIT", "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=6" } }, - "node_modules/@babel/plugin-transform-export-namespace-from": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.24.1.tgz", - "integrity": "sha512-Ft38m/KFOyzKw2UaJFkWG9QnHPG/Q/2SkOrRk4pNBPg5IPZ+dOxcmkK5IyuBcxiNPyyYowPGUReyBvrvZs7IlQ==", + "node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.0", - "@babel/plugin-syntax-export-namespace-from": "^7.8.3" - }, + "license": "MIT", "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=6" } }, - "node_modules/@babel/plugin-transform-for-of": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.24.1.tgz", - "integrity": "sha512-OxBdcnF04bpdQdR3i4giHZNZQn7cm8RQKcSwA17wAAqEELo1ZOwp5FFgeptWUQXFyT9kwHo10aqqauYkRZPCAg==", + "node_modules/camelcase-keys": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-6.2.2.tgz", + "integrity": "sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.0", - "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5" + "camelcase": "^5.3.1", + "map-obj": "^4.0.0", + "quick-lru": "^4.0.1" }, "engines": { - "node": ">=6.9.0" + "node": ">=8" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@babel/plugin-transform-function-name": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.24.1.tgz", - "integrity": "sha512-BXmDZpPlh7jwicKArQASrj8n22/w6iymRnvHYYd2zO30DbE277JO20/7yXJT3QxDPtiQiOxQBbZH4TpivNXIxA==", + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-compilation-targets": "^7.23.6", - "@babel/helper-function-name": "^7.23.0", - "@babel/helper-plugin-utils": "^7.24.0" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, "engines": { - "node": ">=6.9.0" + "node": ">=10" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/@babel/plugin-transform-json-strings": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.24.1.tgz", - "integrity": "sha512-U7RMFmRvoasscrIFy5xA4gIp8iWnWubnKkKuUGJjsuOH7GfbMkB+XZzeslx2kLdEGdOJDamEmCqOks6e8nv8DQ==", + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.0", - "@babel/plugin-syntax-json-strings": "^7.8.3" + "color-name": "~1.1.4" }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=7.0.0" } }, - "node_modules/@babel/plugin-transform-literals": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.24.1.tgz", - "integrity": "sha512-zn9pwz8U7nCqOYIiBaOxoQOtYmMODXTJnkxG4AtX8fPmnCRYWBOHD0qcpwS9e2VDSp1zNJYpdnFMIKb8jmwu6g==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "license": "MIT" + }, + "node_modules/colord": { + "version": "2.9.3", + "resolved": "https://registry.npmjs.org/colord/-/colord-2.9.3.tgz", + "integrity": "sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw==", + "dev": true, + "license": "MIT" }, - "node_modules/@babel/plugin-transform-logical-assignment-operators": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.24.1.tgz", - "integrity": "sha512-OhN6J4Bpz+hIBqItTeWJujDOfNP+unqv/NJgyhlpSqgBTPm37KkMmZV6SYcOj+pnDbdcl1qRGV/ZiIjX9Iy34w==", + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.0", - "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } + "license": "MIT" + }, + "node_modules/confusing-browser-globals": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/confusing-browser-globals/-/confusing-browser-globals-1.0.11.tgz", + "integrity": "sha512-JsPKdmh8ZkmnHxDk55FZ1TqVLvEQTvoByJZRN9jzI0UjxK/QgAmsphz7PGtqgPieQZ/CQcHWXCR7ATDNhGe+YA==", + "dev": true, + "license": "MIT" }, - "node_modules/@babel/plugin-transform-member-expression-literals": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.24.1.tgz", - "integrity": "sha512-4ojai0KysTWXzHseJKa1XPNXKRbuUrhkOPY4rEGeR+7ChlJVKxFa3H3Bz+7tWaGKgJAXUWKOGmltN+u9B3+CVg==", + "node_modules/cosmiconfig": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz", + "integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.0" + "@types/parse-json": "^4.0.0", + "import-fresh": "^3.2.1", + "parse-json": "^5.0.0", + "path-type": "^4.0.0", + "yaml": "^1.10.0" }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=10" } }, - "node_modules/@babel/plugin-transform-modules-amd": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.24.1.tgz", - "integrity": "sha512-lAxNHi4HVtjnHd5Rxg3D5t99Xm6H7b04hUS7EHIXcUl2EV4yl1gWdqZrNzXnSrHveL9qMdbODlLF55mvgjAfaQ==", + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-module-transforms": "^7.23.3", - "@babel/helper-plugin-utils": "^7.24.0" + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">= 8" } }, - "node_modules/@babel/plugin-transform-modules-commonjs": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.24.1.tgz", - "integrity": "sha512-szog8fFTUxBfw0b98gEWPaEqF42ZUD/T3bkynW/wtgx2p/XCP55WEsb+VosKceRSd6njipdZvNogqdtI4Q0chw==", + "node_modules/css-functions-list": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/css-functions-list/-/css-functions-list-3.2.3.tgz", + "integrity": "sha512-IQOkD3hbR5KrN93MtcYuad6YPuTSUhntLHDuLEbFWE+ff2/XSZNdZG+LcbbIW5AXKg/WFIfYItIzVoHngHXZzA==", "dev": true, - "dependencies": { - "@babel/helper-module-transforms": "^7.23.3", - "@babel/helper-plugin-utils": "^7.24.0", - "@babel/helper-simple-access": "^7.22.5" - }, + "license": "MIT", "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=12 || >=16" } }, - "node_modules/@babel/plugin-transform-modules-systemjs": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.24.1.tgz", - "integrity": "sha512-mqQ3Zh9vFO1Tpmlt8QPnbwGHzNz3lpNEMxQb1kAemn/erstyqw1r9KeOlOfo3y6xAnFEcOv2tSyrXfmMk+/YZA==", + "node_modules/cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", "dev": true, - "dependencies": { - "@babel/helper-hoist-variables": "^7.22.5", - "@babel/helper-module-transforms": "^7.23.3", - "@babel/helper-plugin-utils": "^7.24.0", - "@babel/helper-validator-identifier": "^7.22.20" + "license": "MIT", + "bin": { + "cssesc": "bin/cssesc" }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=4" } }, - "node_modules/@babel/plugin-transform-modules-umd": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.24.1.tgz", - "integrity": "sha512-tuA3lpPj+5ITfcCluy6nWonSL7RvaG0AOTeAuvXqEKS34lnLzXpDb0dcP6K8jD0zWZFNDVly90AGFJPnm4fOYg==", + "node_modules/csstype": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", + "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/data-view-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.2.tgz", + "integrity": "sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-module-transforms": "^7.23.3", - "@babel/helper-plugin-utils": "^7.24.0" + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.2" }, "engines": { - "node": ">=6.9.0" + "node": ">= 0.4" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/@babel/plugin-transform-named-capturing-groups-regex": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.22.5.tgz", - "integrity": "sha512-YgLLKmS3aUBhHaxp5hi1WJTgOUb/NCuDHzGT9z9WTt3YG+CPRhJs6nprbStx6DnWM4dh6gt7SU3sZodbZ08adQ==", + "node_modules/data-view-byte-length": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.2.tgz", + "integrity": "sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.22.5", - "@babel/helper-plugin-utils": "^7.22.5" + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.2" }, "engines": { - "node": ">=6.9.0" + "node": ">= 0.4" }, - "peerDependencies": { - "@babel/core": "^7.0.0" + "funding": { + "url": "https://github.com/sponsors/inspect-js" } }, - "node_modules/@babel/plugin-transform-new-target": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.24.1.tgz", - "integrity": "sha512-/rurytBM34hYy0HKZQyA0nHbQgQNFm4Q/BOc9Hflxi2X3twRof7NaE5W46j4kQitm7SvACVRXsa6N/tSZxvPug==", + "node_modules/data-view-byte-offset": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.1.tgz", + "integrity": "sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.0" + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" }, "engines": { - "node": ">=6.9.0" + "node": ">= 0.4" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/@babel/plugin-transform-nullish-coalescing-operator": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.24.1.tgz", - "integrity": "sha512-iQ+caew8wRrhCikO5DrUYx0mrmdhkaELgFa+7baMcVuhxIkN7oxt06CZ51D65ugIb1UWRQ8oQe+HXAVM6qHFjw==", + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.0", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" + "ms": "^2.1.3" }, "engines": { - "node": ">=6.9.0" + "node": ">=6.0" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } } }, - "node_modules/@babel/plugin-transform-numeric-separator": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.24.1.tgz", - "integrity": "sha512-7GAsGlK4cNL2OExJH1DzmDeKnRv/LXq0eLUSvudrehVA5Rgg4bIrqEUW29FbKMBRT0ztSqisv7kjP+XIC4ZMNw==", + "node_modules/decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.0", - "@babel/plugin-syntax-numeric-separator": "^7.10.4" - }, + "license": "MIT", "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=0.10.0" } }, - "node_modules/@babel/plugin-transform-object-rest-spread": { - "version": "7.24.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.24.5.tgz", - "integrity": "sha512-7EauQHszLGM3ay7a161tTQH7fj+3vVM/gThlz5HpFtnygTxjrlvoeq7MPVA1Vy9Q555OB8SnAOsMkLShNkkrHA==", + "node_modules/decamelize-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/decamelize-keys/-/decamelize-keys-1.1.1.tgz", + "integrity": "sha512-WiPxgEirIV0/eIOMcnFBA3/IJZAZqKnwAwWyvvdi4lsr1WCN22nhdf/3db3DoZcUjTV2SqfzIwNyp6y2xs3nmg==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-compilation-targets": "^7.23.6", - "@babel/helper-plugin-utils": "^7.24.5", - "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-transform-parameters": "^7.24.5" + "decamelize": "^1.1.0", + "map-obj": "^1.0.0" }, "engines": { - "node": ">=6.9.0" + "node": ">=0.10.0" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@babel/plugin-transform-object-super": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.24.1.tgz", - "integrity": "sha512-oKJqR3TeI5hSLRxudMjFQ9re9fBVUU0GICqM3J1mi8MqlhVr6hC/ZN4ttAyMuQR6EZZIY6h/exe5swqGNNIkWQ==", + "node_modules/decamelize-keys/node_modules/map-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", + "integrity": "sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg==", "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.0", - "@babel/helper-replace-supers": "^7.24.1" - }, + "license": "MIT", "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=0.10.0" } }, - "node_modules/@babel/plugin-transform-optional-catch-binding": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.24.1.tgz", - "integrity": "sha512-oBTH7oURV4Y+3EUrf6cWn1OHio3qG/PVwO5J03iSJmBg6m2EhKjkAu/xuaXaYwWW9miYtvbWv4LNf0AmR43LUA==", + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.0", - "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" }, "engines": { - "node": ">=6.9.0" + "node": ">= 0.4" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/@babel/plugin-transform-optional-chaining": { - "version": "7.24.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.24.5.tgz", - "integrity": "sha512-xWCkmwKT+ihmA6l7SSTpk8e4qQl/274iNbSKRRS8mpqFR32ksy36+a+LWY8OXCCEefF8WFlnOHVsaDI2231wBg==", + "node_modules/define-properties": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.5", - "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5", - "@babel/plugin-syntax-optional-chaining": "^7.8.3" + "define-data-property": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" }, "engines": { - "node": ">=6.9.0" + "node": ">= 0.4" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/@babel/plugin-transform-parameters": { - "version": "7.24.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.24.5.tgz", - "integrity": "sha512-9Co00MqZ2aoky+4j2jhofErthm6QVLKbpQrvz20c3CH9KQCLHyNB+t2ya4/UrRpQGR+Wrwjg9foopoeSdnHOkA==", + "node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.5" + "path-type": "^4.0.0" }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=8" } }, - "node_modules/@babel/plugin-transform-private-methods": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.24.1.tgz", - "integrity": "sha512-tGvisebwBO5em4PaYNqt4fkw56K2VALsAbAakY0FjTYqJp7gfdrgr7YX76Or8/cpik0W6+tj3rZ0uHU9Oil4tw==", + "node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", "dev": true, + "license": "Apache-2.0", "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.24.1", - "@babel/helper-plugin-utils": "^7.24.0" + "esutils": "^2.0.2" }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=6.0.0" } }, - "node_modules/@babel/plugin-transform-private-property-in-object": { - "version": "7.24.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.24.5.tgz", - "integrity": "sha512-JM4MHZqnWR04jPMujQDTBVRnqxpLLpx2tkn7iPn+Hmsc0Gnb79yvRWOkvqFOx3Z7P7VxiRIR22c4eGSNj87OBQ==", + "node_modules/dom-serializer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", + "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.22.5", - "@babel/helper-create-class-features-plugin": "^7.24.5", - "@babel/helper-plugin-utils": "^7.24.5", - "@babel/plugin-syntax-private-property-in-object": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" + "domelementtype": "^2.3.0", + "domhandler": "^5.0.2", + "entities": "^4.2.0" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" } }, - "node_modules/@babel/plugin-transform-property-literals": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.24.1.tgz", - "integrity": "sha512-LetvD7CrHmEx0G442gOomRr66d7q8HzzGGr4PMHGr+5YIm6++Yke+jxj246rpvsbyhJwCLxcTn6zW1P1BSenqA==", + "node_modules/domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "license": "BSD-2-Clause" + }, + "node_modules/domhandler": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", + "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.0" + "domelementtype": "^2.3.0" }, "engines": { - "node": ">=6.9.0" + "node": ">= 4" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" } }, - "node_modules/@babel/plugin-transform-regenerator": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.24.1.tgz", - "integrity": "sha512-sJwZBCzIBE4t+5Q4IGLaaun5ExVMRY0lYwos/jNecjMrVCygCdph3IKv0tkP5Fc87e/1+bebAmEAGBfnRD+cnw==", + "node_modules/domutils": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.2.2.tgz", + "integrity": "sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.0", - "regenerator-transform": "^0.15.2" - }, - "engines": { - "node": ">=6.9.0" + "dom-serializer": "^2.0.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" } }, - "node_modules/@babel/plugin-transform-reserved-words": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.24.1.tgz", - "integrity": "sha512-JAclqStUfIwKN15HrsQADFgeZt+wexNQ0uLhuqvqAUFoqPMjEcFCYZBhq0LUdz6dZK/mD+rErhW71fbx8RYElg==", + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.0" + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">= 0.4" } }, - "node_modules/@babel/plugin-transform-runtime": { - "version": "7.24.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.24.3.tgz", - "integrity": "sha512-J0BuRPNlNqlMTRJ72eVptpt9VcInbxO6iP3jaxr+1NPhC0UkKL+6oeX6VXMEYdADnuqmMmsBspt4d5w8Y/TCbQ==", + "node_modules/emoji-regex": { + "version": "10.6.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.6.0.tgz", + "integrity": "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==", "dev": true, - "dependencies": { - "@babel/helper-module-imports": "^7.24.3", - "@babel/helper-plugin-utils": "^7.24.0", - "babel-plugin-polyfill-corejs2": "^0.4.10", - "babel-plugin-polyfill-corejs3": "^0.10.1", - "babel-plugin-polyfill-regenerator": "^0.6.1", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" + "license": "MIT" + }, + "node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" } }, - "node_modules/@babel/plugin-transform-shorthand-properties": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.24.1.tgz", - "integrity": "sha512-LyjVB1nsJ6gTTUKRjRWx9C1s9hE7dLfP/knKdrfeH9UPtAGjYGgxIbFfx7xyLIEWs7Xe1Gnf8EWiUqfjLhInZA==", + "node_modules/error-ex": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.4.tgz", + "integrity": "sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "is-arrayish": "^0.2.1" } }, - "node_modules/@babel/plugin-transform-spread": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.24.1.tgz", - "integrity": "sha512-KjmcIM+fxgY+KxPVbjelJC6hrH1CgtPmTvdXAfn3/a9CnWGSTY7nH4zm5+cjmWJybdcPSsD0++QssDsjcpe47g==", + "node_modules/es-abstract": { + "version": "1.24.0", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.24.0.tgz", + "integrity": "sha512-WSzPgsdLtTcQwm4CROfS5ju2Wa1QQcVeT37jFjYzdFz1r9ahadC8B8/a4qxJxM+09F18iumCdRmlr96ZYkQvEg==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.0", - "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5" + "array-buffer-byte-length": "^1.0.2", + "arraybuffer.prototype.slice": "^1.0.4", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "data-view-buffer": "^1.0.2", + "data-view-byte-length": "^1.0.2", + "data-view-byte-offset": "^1.0.1", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "es-set-tostringtag": "^2.1.0", + "es-to-primitive": "^1.3.0", + "function.prototype.name": "^1.1.8", + "get-intrinsic": "^1.3.0", + "get-proto": "^1.0.1", + "get-symbol-description": "^1.1.0", + "globalthis": "^1.0.4", + "gopd": "^1.2.0", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "internal-slot": "^1.1.0", + "is-array-buffer": "^3.0.5", + "is-callable": "^1.2.7", + "is-data-view": "^1.0.2", + "is-negative-zero": "^2.0.3", + "is-regex": "^1.2.1", + "is-set": "^2.0.3", + "is-shared-array-buffer": "^1.0.4", + "is-string": "^1.1.1", + "is-typed-array": "^1.1.15", + "is-weakref": "^1.1.1", + "math-intrinsics": "^1.1.0", + "object-inspect": "^1.13.4", + "object-keys": "^1.1.1", + "object.assign": "^4.1.7", + "own-keys": "^1.0.1", + "regexp.prototype.flags": "^1.5.4", + "safe-array-concat": "^1.1.3", + "safe-push-apply": "^1.0.0", + "safe-regex-test": "^1.1.0", + "set-proto": "^1.0.0", + "stop-iteration-iterator": "^1.1.0", + "string.prototype.trim": "^1.2.10", + "string.prototype.trimend": "^1.0.9", + "string.prototype.trimstart": "^1.0.8", + "typed-array-buffer": "^1.0.3", + "typed-array-byte-length": "^1.0.3", + "typed-array-byte-offset": "^1.0.4", + "typed-array-length": "^1.0.7", + "unbox-primitive": "^1.1.0", + "which-typed-array": "^1.1.19" }, "engines": { - "node": ">=6.9.0" + "node": ">= 0.4" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/@babel/plugin-transform-sticky-regex": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.24.1.tgz", - "integrity": "sha512-9v0f1bRXgPVcPrngOQvLXeGNNVLc8UjMVfebo9ka0WF3/7+aVUHmaJVT3sa0XCzEFioPfPHZiOcYG9qOsH63cw==", + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.0" - }, + "license": "MIT", "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">= 0.4" } }, - "node_modules/@babel/plugin-transform-template-literals": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.24.1.tgz", - "integrity": "sha512-WRkhROsNzriarqECASCNu/nojeXCDTE/F2HmRgOzi7NGvyfYGq1NEjKBK3ckLfRgGc6/lPAqP0vDOSw3YtG34g==", + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.0" - }, + "license": "MIT", "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">= 0.4" } }, - "node_modules/@babel/plugin-transform-typeof-symbol": { - "version": "7.24.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.24.5.tgz", - "integrity": "sha512-UTGnhYVZtTAjdwOTzT+sCyXmTn8AhaxOS/MjG9REclZ6ULHWF9KoCZur0HSGU7hk8PdBFKKbYe6+gqdXWz84Jg==", + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.5" + "es-errors": "^1.3.0" }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">= 0.4" } }, - "node_modules/@babel/plugin-transform-typescript": { - "version": "7.24.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.24.5.tgz", - "integrity": "sha512-E0VWu/hk83BIFUWnsKZ4D81KXjN5L3MobvevOHErASk9IPwKHOkTgvqzvNo1yP/ePJWqqK2SpUR5z+KQbl6NVw==", + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.22.5", - "@babel/helper-create-class-features-plugin": "^7.24.5", - "@babel/helper-plugin-utils": "^7.24.5", - "@babel/plugin-syntax-typescript": "^7.24.1" + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">= 0.4" } }, - "node_modules/@babel/plugin-transform-unicode-escapes": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.24.1.tgz", - "integrity": "sha512-RlkVIcWT4TLI96zM660S877E7beKlQw7Ig+wqkKBiWfj0zH5Q4h50q6er4wzZKRNSYpfo6ILJ+hrJAGSX2qcNw==", + "node_modules/es-shim-unscopables": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.1.0.tgz", + "integrity": "sha512-d9T8ucsEhh8Bi1woXCf+TIKDIROLG5WCkxg8geBCbvk22kzwC5G2OnXVMO6FUsvQlgUUXQ2itephWDLqDzbeCw==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.0" + "hasown": "^2.0.2" }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">= 0.4" } }, - "node_modules/@babel/plugin-transform-unicode-property-regex": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.24.1.tgz", - "integrity": "sha512-Ss4VvlfYV5huWApFsF8/Sq0oXnGO+jB+rijFEFugTd3cwSObUSnUi88djgR5528Csl0uKlrI331kRqe56Ov2Ng==", + "node_modules/es-to-primitive": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.3.0.tgz", + "integrity": "sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.22.15", - "@babel/helper-plugin-utils": "^7.24.0" + "is-callable": "^1.2.7", + "is-date-object": "^1.0.5", + "is-symbol": "^1.0.4" }, "engines": { - "node": ">=6.9.0" + "node": ">= 0.4" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/@babel/plugin-transform-unicode-regex": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.24.1.tgz", - "integrity": "sha512-2A/94wgZgxfTsiLaQ2E36XAOdcZmGAaEEgVmxQWwZXWkGhvoHbaqXcKnU8zny4ycpu3vNqg0L/PcCiYtHtA13g==", + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", "dev": true, - "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.22.15", - "@babel/helper-plugin-utils": "^7.24.0" - }, + "license": "MIT", "engines": { - "node": ">=6.9.0" + "node": ">=10" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@babel/plugin-transform-unicode-sets-regex": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.24.1.tgz", - "integrity": "sha512-fqj4WuzzS+ukpgerpAoOnMfQXwUHFxXUZUE84oL2Kao2N8uSlvcpnAidKASgsNgzZHBsHWvcm8s9FPWUhAb8fA==", + "node_modules/eslint": { + "version": "8.57.1", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.1.tgz", + "integrity": "sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==", + "deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.22.15", - "@babel/helper-plugin-utils": "^7.24.0" - }, - "engines": { - "node": ">=6.9.0" + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/eslintrc": "^2.1.4", + "@eslint/js": "8.57.1", + "@humanwhocodes/config-array": "^0.13.0", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "@ungap/structured-clone": "^1.2.0", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.2.2", + "eslint-visitor-keys": "^3.4.3", + "espree": "^9.6.1", + "esquery": "^1.4.2", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "graphemer": "^1.4.0", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3", + "strip-ansi": "^6.0.1", + "text-table": "^0.2.0" }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/preset-env": { - "version": "7.24.5", - "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.24.5.tgz", - "integrity": "sha512-UGK2ifKtcC8i5AI4cH+sbLLuLc2ktYSFJgBAXorKAsHUZmrQ1q6aQ6i3BvU24wWs2AAKqQB6kq3N9V9Gw1HiMQ==", - "dev": true, - "dependencies": { - "@babel/compat-data": "^7.24.4", - "@babel/helper-compilation-targets": "^7.23.6", - "@babel/helper-plugin-utils": "^7.24.5", - "@babel/helper-validator-option": "^7.23.5", - "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.24.5", - "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.24.1", - "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.24.1", - "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.24.1", - "@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2", - "@babel/plugin-syntax-async-generators": "^7.8.4", - "@babel/plugin-syntax-class-properties": "^7.12.13", - "@babel/plugin-syntax-class-static-block": "^7.14.5", - "@babel/plugin-syntax-dynamic-import": "^7.8.3", - "@babel/plugin-syntax-export-namespace-from": "^7.8.3", - "@babel/plugin-syntax-import-assertions": "^7.24.1", - "@babel/plugin-syntax-import-attributes": "^7.24.1", - "@babel/plugin-syntax-import-meta": "^7.10.4", - "@babel/plugin-syntax-json-strings": "^7.8.3", - "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", - "@babel/plugin-syntax-numeric-separator": "^7.10.4", - "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", - "@babel/plugin-syntax-optional-chaining": "^7.8.3", - "@babel/plugin-syntax-private-property-in-object": "^7.14.5", - "@babel/plugin-syntax-top-level-await": "^7.14.5", - "@babel/plugin-syntax-unicode-sets-regex": "^7.18.6", - "@babel/plugin-transform-arrow-functions": "^7.24.1", - "@babel/plugin-transform-async-generator-functions": "^7.24.3", - "@babel/plugin-transform-async-to-generator": "^7.24.1", - "@babel/plugin-transform-block-scoped-functions": "^7.24.1", - "@babel/plugin-transform-block-scoping": "^7.24.5", - "@babel/plugin-transform-class-properties": "^7.24.1", - "@babel/plugin-transform-class-static-block": "^7.24.4", - "@babel/plugin-transform-classes": "^7.24.5", - "@babel/plugin-transform-computed-properties": "^7.24.1", - "@babel/plugin-transform-destructuring": "^7.24.5", - "@babel/plugin-transform-dotall-regex": "^7.24.1", - "@babel/plugin-transform-duplicate-keys": "^7.24.1", - "@babel/plugin-transform-dynamic-import": "^7.24.1", - "@babel/plugin-transform-exponentiation-operator": "^7.24.1", - "@babel/plugin-transform-export-namespace-from": "^7.24.1", - "@babel/plugin-transform-for-of": "^7.24.1", - "@babel/plugin-transform-function-name": "^7.24.1", - "@babel/plugin-transform-json-strings": "^7.24.1", - "@babel/plugin-transform-literals": "^7.24.1", - "@babel/plugin-transform-logical-assignment-operators": "^7.24.1", - "@babel/plugin-transform-member-expression-literals": "^7.24.1", - "@babel/plugin-transform-modules-amd": "^7.24.1", - "@babel/plugin-transform-modules-commonjs": "^7.24.1", - "@babel/plugin-transform-modules-systemjs": "^7.24.1", - "@babel/plugin-transform-modules-umd": "^7.24.1", - "@babel/plugin-transform-named-capturing-groups-regex": "^7.22.5", - "@babel/plugin-transform-new-target": "^7.24.1", - "@babel/plugin-transform-nullish-coalescing-operator": "^7.24.1", - "@babel/plugin-transform-numeric-separator": "^7.24.1", - "@babel/plugin-transform-object-rest-spread": "^7.24.5", - "@babel/plugin-transform-object-super": "^7.24.1", - "@babel/plugin-transform-optional-catch-binding": "^7.24.1", - "@babel/plugin-transform-optional-chaining": "^7.24.5", - "@babel/plugin-transform-parameters": "^7.24.5", - "@babel/plugin-transform-private-methods": "^7.24.1", - "@babel/plugin-transform-private-property-in-object": "^7.24.5", - "@babel/plugin-transform-property-literals": "^7.24.1", - "@babel/plugin-transform-regenerator": "^7.24.1", - "@babel/plugin-transform-reserved-words": "^7.24.1", - "@babel/plugin-transform-shorthand-properties": "^7.24.1", - "@babel/plugin-transform-spread": "^7.24.1", - "@babel/plugin-transform-sticky-regex": "^7.24.1", - "@babel/plugin-transform-template-literals": "^7.24.1", - "@babel/plugin-transform-typeof-symbol": "^7.24.5", - "@babel/plugin-transform-unicode-escapes": "^7.24.1", - "@babel/plugin-transform-unicode-property-regex": "^7.24.1", - "@babel/plugin-transform-unicode-regex": "^7.24.1", - "@babel/plugin-transform-unicode-sets-regex": "^7.24.1", - "@babel/preset-modules": "0.1.6-no-external-plugins", - "babel-plugin-polyfill-corejs2": "^0.4.10", - "babel-plugin-polyfill-corejs3": "^0.10.4", - "babel-plugin-polyfill-regenerator": "^0.6.1", - "core-js-compat": "^3.31.0", - "semver": "^6.3.1" + "bin": { + "eslint": "bin/eslint.js" }, "engines": { - "node": ">=6.9.0" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "funding": { + "url": "https://opencollective.com/eslint" } }, - "node_modules/@babel/preset-modules": { - "version": "0.1.6-no-external-plugins", - "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.6-no-external-plugins.tgz", - "integrity": "sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA==", + "node_modules/eslint-config-airbnb-base": { + "version": "15.0.0", + "resolved": "https://registry.npmjs.org/eslint-config-airbnb-base/-/eslint-config-airbnb-base-15.0.0.tgz", + "integrity": "sha512-xaX3z4ZZIcFLvh2oUNvcX5oEofXda7giYmuplVxoOg5A7EXJMrUyqRgR+mhDhPK8LZ4PttFOBvCYDbX3sUoUig==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/types": "^7.4.4", - "esutils": "^2.0.2" + "confusing-browser-globals": "^1.0.10", + "object.assign": "^4.1.2", + "object.entries": "^1.1.5", + "semver": "^6.3.0" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" }, "peerDependencies": { - "@babel/core": "^7.0.0-0 || ^8.0.0-0 <8.0.0" + "eslint": "^7.32.0 || ^8.2.0", + "eslint-plugin-import": "^2.25.2" } }, - "node_modules/@babel/preset-typescript": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.24.1.tgz", - "integrity": "sha512-1DBaMmRDpuYQBPWD8Pf/WEwCrtgRHxsZnP4mIy9G/X+hFfbI47Q2G4t1Paakld84+qsk2fSsUPMKg71jkoOOaQ==", + "node_modules/eslint-config-airbnb-base/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.0", - "@babel/helper-validator-option": "^7.23.5", - "@babel/plugin-syntax-jsx": "^7.24.1", - "@babel/plugin-transform-modules-commonjs": "^7.24.1", - "@babel/plugin-transform-typescript": "^7.24.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "license": "ISC", + "bin": { + "semver": "bin/semver.js" } }, - "node_modules/@babel/register": { - "version": "7.23.7", - "resolved": "https://registry.npmjs.org/@babel/register/-/register-7.23.7.tgz", - "integrity": "sha512-EjJeB6+kvpk+Y5DAkEAmbOBEFkh9OASx0huoEkqYTFxAZHzOAX2Oh5uwAUuL2rUddqfM0SA+KPXV2TbzoZ2kvQ==", + "node_modules/eslint-config-prettier": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.1.0.tgz", + "integrity": "sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==", "dev": true, - "dependencies": { - "clone-deep": "^4.0.1", - "find-cache-dir": "^2.0.0", - "make-dir": "^2.1.0", - "pirates": "^4.0.6", - "source-map-support": "^0.5.16" - }, - "engines": { - "node": ">=6.9.0" + "license": "MIT", + "bin": { + "eslint-config-prettier": "bin/cli.js" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "eslint": ">=7.0.0" } }, - "node_modules/@babel/regjsgen": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/@babel/regjsgen/-/regjsgen-0.8.0.tgz", - "integrity": "sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA==", - "dev": true - }, - "node_modules/@babel/runtime": { - "version": "7.24.5", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.24.5.tgz", - "integrity": "sha512-Nms86NXrsaeU9vbBJKni6gXiEXZ4CVpYVzEjDH9Sb8vmZ3UljyA1GSOJl/6LGPO8EHLuSF9H+IxNXHPX8QHJ4g==", + "node_modules/eslint-import-resolver-node": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz", + "integrity": "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==", "dev": true, + "license": "MIT", "dependencies": { - "regenerator-runtime": "^0.14.0" - }, - "engines": { - "node": ">=6.9.0" + "debug": "^3.2.7", + "is-core-module": "^2.13.0", + "resolve": "^1.22.4" } }, - "node_modules/@babel/template": { - "version": "7.24.0", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.24.0.tgz", - "integrity": "sha512-Bkf2q8lMB0AFpX0NFEqSbx1OkTHf0f+0j82mkw+ZpzBnkk7e9Ql0891vlfgi+kHwOk8tQjiQHpqh4LaSa0fKEA==", + "node_modules/eslint-import-resolver-node/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.23.5", - "@babel/parser": "^7.24.0", - "@babel/types": "^7.24.0" - }, - "engines": { - "node": ">=6.9.0" + "ms": "^2.1.1" } }, - "node_modules/@babel/traverse": { - "version": "7.24.5", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.24.5.tgz", - "integrity": "sha512-7aaBLeDQ4zYcUFDUD41lJc1fG8+5IU9DaNSJAgal866FGvmD5EbWQgnEC6kO1gGLsX0esNkfnJSndbTXA3r7UA==", + "node_modules/eslint-module-utils": { + "version": "2.12.1", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.12.1.tgz", + "integrity": "sha512-L8jSWTze7K2mTg0vos/RuLRS5soomksDPoJLXIslC7c8Wmut3bx7CPpJijDcBZtxQ5lrbUdM+s0OlNbz0DCDNw==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.24.2", - "@babel/generator": "^7.24.5", - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-function-name": "^7.23.0", - "@babel/helper-hoist-variables": "^7.22.5", - "@babel/helper-split-export-declaration": "^7.24.5", - "@babel/parser": "^7.24.5", - "@babel/types": "^7.24.5", - "debug": "^4.3.1", - "globals": "^11.1.0" + "debug": "^3.2.7" }, "engines": { - "node": ">=6.9.0" + "node": ">=4" + }, + "peerDependenciesMeta": { + "eslint": { + "optional": true + } } }, - "node_modules/@babel/types": { - "version": "7.24.5", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.24.5.tgz", - "integrity": "sha512-6mQNsaLeXTw0nxYUYu+NSa4Hx4BlF1x1x8/PMFbiR+GBSr+2DkECc69b8hgy2frEodNcvPffeH8YfWd3LI6jhQ==", + "node_modules/eslint-module-utils/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-string-parser": "^7.24.1", - "@babel/helper-validator-identifier": "^7.24.5", - "to-fast-properties": "^2.0.0" - }, - "engines": { - "node": ">=6.9.0" + "ms": "^2.1.1" } }, - "node_modules/@csstools/css-parser-algorithms": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@csstools/css-parser-algorithms/-/css-parser-algorithms-3.0.4.tgz", - "integrity": "sha512-Up7rBoV77rv29d3uKHUIVubz1BTcgyUK72IvCQAbfbMv584xHcGKCKbWh7i8hPrRJ7qU4Y8IO3IY9m+iTB7P3A==", + "node_modules/eslint-plugin-file-progress": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-file-progress/-/eslint-plugin-file-progress-1.5.0.tgz", + "integrity": "sha512-get8oNfacIagP+igSzrEZhepPgodtdwACVeKQsE1fVvTL15tZvgCv8K4B2lKT4FZOZOyhxSkQGnWyjEOx1uoIw==", "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/csstools" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - } - ], "license": "MIT", - "engines": { - "node": ">=18" + "dependencies": { + "nanospinner": "^1.1.0", + "picocolors": "^1.0.1" }, "peerDependencies": { - "@csstools/css-tokenizer": "^3.0.3" + "eslint": "^7.0.0 || ^8.0.0 || ^9.0.0" } }, - "node_modules/@csstools/css-tokenizer": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@csstools/css-tokenizer/-/css-tokenizer-3.0.3.tgz", - "integrity": "sha512-UJnjoFsmxfKUdNYdWgOB0mWUypuLvAfQPH1+pyvRJs6euowbFkFC6P13w1l8mJyi3vxYMxc9kld5jZEGRQs6bw==", + "node_modules/eslint-plugin-filename-rules": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-filename-rules/-/eslint-plugin-filename-rules-1.3.1.tgz", + "integrity": "sha512-kBMxGFvK3QrRBHMurhFSNa+PFdszezVtBV6egg39TDzlj6D4jL3Xx6oyNjm5xE4C+TdQUBzWwymHJHBPyxOreA==", "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/csstools" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - } - ], "license": "MIT", "engines": { - "node": ">=18" + "node": ">=6.0.0" } }, - "node_modules/@csstools/media-query-list-parser": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/@csstools/media-query-list-parser/-/media-query-list-parser-4.0.2.tgz", - "integrity": "sha512-EUos465uvVvMJehckATTlNqGj4UJWkTmdWuDMjqvSUkjGpmOyFZBVwb4knxCm/k2GMTXY+c/5RkdndzFYWeX5A==", + "node_modules/eslint-plugin-html": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-html/-/eslint-plugin-html-7.1.0.tgz", + "integrity": "sha512-fNLRraV/e6j8e3XYOC9xgND4j+U7b1Rq+OygMlLcMg+wI/IpVbF+ubQa3R78EjKB9njT6TQOlcK5rFKBVVtdfg==", + "dev": true, + "license": "ISC", + "dependencies": { + "htmlparser2": "^8.0.1" + } + }, + "node_modules/eslint-plugin-import": { + "version": "2.31.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.31.0.tgz", + "integrity": "sha512-ixmkI62Rbc2/w8Vfxyh1jQRTdRTF52VxwRVHl/ykPAmqG+Nb7/kNn+byLP0LxPgI7zWA16Jt82SybJInmMia3A==", "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/csstools" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - } - ], "license": "MIT", + "dependencies": { + "@rtsao/scc": "^1.1.0", + "array-includes": "^3.1.8", + "array.prototype.findlastindex": "^1.2.5", + "array.prototype.flat": "^1.3.2", + "array.prototype.flatmap": "^1.3.2", + "debug": "^3.2.7", + "doctrine": "^2.1.0", + "eslint-import-resolver-node": "^0.3.9", + "eslint-module-utils": "^2.12.0", + "hasown": "^2.0.2", + "is-core-module": "^2.15.1", + "is-glob": "^4.0.3", + "minimatch": "^3.1.2", + "object.fromentries": "^2.0.8", + "object.groupby": "^1.0.3", + "object.values": "^1.2.0", + "semver": "^6.3.1", + "string.prototype.trimend": "^1.0.8", + "tsconfig-paths": "^3.15.0" + }, "engines": { - "node": ">=18" + "node": ">=4" }, "peerDependencies": { - "@csstools/css-parser-algorithms": "^3.0.4", - "@csstools/css-tokenizer": "^3.0.3" + "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 || ^9" } }, - "node_modules/@dual-bundle/import-meta-resolve": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/@dual-bundle/import-meta-resolve/-/import-meta-resolve-4.1.0.tgz", - "integrity": "sha512-+nxncfwHM5SgAtrVzgpzJOI1ol0PkumhVo469KCf9lUi21IGcY90G98VuHm9VRrUypmAzawAHO9bs6hqeADaVg==", + "node_modules/eslint-plugin-import/node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", "dev": true, "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" } }, - "node_modules/@esbuild/aix-ppc64": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.1.tgz", - "integrity": "sha512-kfYGy8IdzTGy+z0vFGvExZtxkFlA4zAxgKEahG9KE1ScBjpQnFsNOX8KTU5ojNru5ed5CVoJYXFtoxaq5nFbjQ==", - "cpu": [ - "ppc64" - ], + "node_modules/eslint-plugin-import/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "aix" - ], - "peer": true, - "engines": { - "node": ">=18" + "dependencies": { + "ms": "^2.1.1" } }, - "node_modules/@esbuild/android-arm": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.1.tgz", - "integrity": "sha512-dp+MshLYux6j/JjdqVLnMglQlFu+MuVeNrmT5nk6q07wNhCdSnB7QZj+7G8VMUGh1q+vj2Bq8kRsuyA00I/k+Q==", - "cpu": [ - "arm" - ], + "node_modules/eslint-plugin-import/node_modules/doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "peer": true, + "license": "Apache-2.0", + "dependencies": { + "esutils": "^2.0.2" + }, "engines": { - "node": ">=18" + "node": ">=0.10.0" } }, - "node_modules/@esbuild/android-arm64": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.1.tgz", - "integrity": "sha512-50tM0zCJW5kGqgG7fQ7IHvQOcAn9TKiVRuQ/lN0xR+T2lzEFvAi1ZcS8DiksFcEpf1t/GYOeOfCAgDHFpkiSmA==", - "cpu": [ - "arm64" - ], + "node_modules/eslint-plugin-import/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "peer": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, "engines": { - "node": ">=18" + "node": "*" } }, - "node_modules/@esbuild/android-x64": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.1.tgz", - "integrity": "sha512-GCj6WfUtNldqUzYkN/ITtlhwQqGWu9S45vUXs7EIYf+7rCiiqH9bCloatO9VhxsL0Pji+PF4Lz2XXCES+Q8hDw==", - "cpu": [ - "x64" - ], + "node_modules/eslint-plugin-import/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "peer": true, - "engines": { - "node": ">=18" + "license": "ISC", + "bin": { + "semver": "bin/semver.js" } }, - "node_modules/@esbuild/darwin-arm64": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.1.tgz", - "integrity": "sha512-5hEZKPf+nQjYoSr/elb62U19/l1mZDdqidGfmFutVUjjUZrOazAtwK+Kr+3y0C/oeJfLlxo9fXb1w7L+P7E4FQ==", - "cpu": [ - "arm64" - ], + "node_modules/eslint-plugin-inclusive-language": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-inclusive-language/-/eslint-plugin-inclusive-language-2.2.1.tgz", + "integrity": "sha512-RL6avDWXCS0Dcp9axhvHRUp65qG07qjOrh6J4BNNahPvRY3PuYGnAd0H1strZ9cob79JiEW4Bq0j3gEuzbv0/A==", "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "peer": true, - "engines": { - "node": ">=18" + "license": "CC0-1.0", + "dependencies": { + "humps": "^2.0.1" } }, - "node_modules/@esbuild/darwin-x64": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.1.tgz", - "integrity": "sha512-hxVnwL2Dqs3fM1IWq8Iezh0cX7ZGdVhbTfnOy5uURtao5OIVCEyj9xIzemDi7sRvKsuSdtCAhMKarxqtlyVyfA==", - "cpu": [ - "x64" - ], + "node_modules/eslint-plugin-vue": { + "version": "9.32.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-9.32.0.tgz", + "integrity": "sha512-b/Y05HYmnB/32wqVcjxjHZzNpwxj1onBOvqW89W+V+XNG1dRuaFbNd3vT9CLbr2LXjEoq+3vn8DanWf7XU22Ug==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "peer": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.4.0", + "globals": "^13.24.0", + "natural-compare": "^1.4.0", + "nth-check": "^2.1.1", + "postcss-selector-parser": "^6.0.15", + "semver": "^7.6.3", + "vue-eslint-parser": "^9.4.3", + "xml-name-validator": "^4.0.0" + }, "engines": { - "node": ">=18" + "node": "^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": "^6.2.0 || ^7.0.0 || ^8.0.0 || ^9.0.0" } }, - "node_modules/@esbuild/freebsd-arm64": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.1.tgz", - "integrity": "sha512-1MrCZs0fZa2g8E+FUo2ipw6jw5qqQiH+tERoS5fAfKnRx6NXH31tXBKI3VpmLijLH6yriMZsxJtaXUyFt/8Y4A==", - "cpu": [ - "arm64" - ], + "node_modules/eslint-plugin-vuejs-accessibility": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-vuejs-accessibility/-/eslint-plugin-vuejs-accessibility-2.4.1.tgz", + "integrity": "sha512-ZRZhPdslplZXSF71MtSG+zXYRAT5KiHR4JVuo/DERQf9noAkDvi5W418VOE1qllmJd7wTenndxi1q8XeDMxdHw==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "peer": true, + "dependencies": { + "aria-query": "^5.3.0", + "emoji-regex": "^10.0.0", + "vue-eslint-parser": "^9.0.1" + }, "engines": { - "node": ">=18" + "node": ">=16.0.0" + }, + "peerDependencies": { + "eslint": "^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 || ^9.0.0" } }, - "node_modules/@esbuild/freebsd-x64": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.1.tgz", - "integrity": "sha512-0IZWLiTyz7nm0xuIs0q1Y3QWJC52R8aSXxe40VUxm6BB1RNmkODtW6LHvWRrGiICulcX7ZvyH6h5fqdLu4gkww==", - "cpu": [ - "x64" - ], + "node_modules/eslint-scope": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", + "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "peer": true, + "license": "BSD-2-Clause", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, "engines": { - "node": ">=18" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, - "node_modules/@esbuild/linux-arm": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.1.tgz", - "integrity": "sha512-NdKOhS4u7JhDKw9G3cY6sWqFcnLITn6SqivVArbzIaf3cemShqfLGHYMx8Xlm/lBit3/5d7kXvriTUGa5YViuQ==", - "cpu": [ - "arm" - ], + "node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "peer": true, + "license": "Apache-2.0", "engines": { - "node": ">=18" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, - "node_modules/@esbuild/linux-arm64": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.1.tgz", - "integrity": "sha512-jaN3dHi0/DDPelk0nLcXRm1q7DNJpjXy7yWaWvbfkPvI+7XNSc/lDOnCLN7gzsyzgu6qSAmgSvP9oXAhP973uQ==", - "cpu": [ - "arm64" - ], + "node_modules/eslint/node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "peer": true, - "engines": { - "node": ">=18" + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" } }, - "node_modules/@esbuild/linux-ia32": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.1.tgz", - "integrity": "sha512-OJykPaF4v8JidKNGz8c/q1lBO44sQNUQtq1KktJXdBLn1hPod5rE/Hko5ugKKZd+D2+o1a9MFGUEIUwO2YfgkQ==", - "cpu": [ - "ia32" - ], + "node_modules/eslint/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "peer": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, "engines": { - "node": ">=18" + "node": "*" } }, - "node_modules/@esbuild/linux-loong64": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.1.tgz", - "integrity": "sha512-nGfornQj4dzcq5Vp835oM/o21UMlXzn79KobKlcs3Wz9smwiifknLy4xDCLUU0BWp7b/houtdrgUz7nOGnfIYg==", - "cpu": [ - "loong64" - ], + "node_modules/espree": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "peer": true, + "license": "BSD-2-Clause", + "dependencies": { + "acorn": "^8.9.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.1" + }, "engines": { - "node": ">=18" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, - "node_modules/@esbuild/linux-mips64el": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.1.tgz", - "integrity": "sha512-1osBbPEFYwIE5IVB/0g2X6i1qInZa1aIoj1TdL4AaAb55xIIgbg8Doq6a5BzYWgr+tEcDzYH67XVnTmUzL+nXg==", - "cpu": [ - "mips64el" - ], + "node_modules/esquery": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", + "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "peer": true, + "license": "BSD-3-Clause", + "dependencies": { + "estraverse": "^5.1.0" + }, "engines": { - "node": ">=18" + "node": ">=0.10" } }, - "node_modules/@esbuild/linux-ppc64": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.1.tgz", - "integrity": "sha512-/6VBJOwUf3TdTvJZ82qF3tbLuWsscd7/1w+D9LH0W/SqUgM5/JJD0lrJ1fVIfZsqB6RFmLCe0Xz3fmZc3WtyVg==", - "cpu": [ - "ppc64" - ], + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "peer": true, + "license": "BSD-2-Clause", + "dependencies": { + "estraverse": "^5.2.0" + }, "engines": { - "node": ">=18" + "node": ">=4.0" } }, - "node_modules/@esbuild/linux-riscv64": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.1.tgz", - "integrity": "sha512-nSut/Mx5gnilhcq2yIMLMe3Wl4FK5wx/o0QuuCLMtmJn+WeWYoEGDN1ipcN72g1WHsnIbxGXd4i/MF0gTcuAjQ==", - "cpu": [ - "riscv64" - ], + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "peer": true, + "license": "BSD-2-Clause", "engines": { - "node": ">=18" + "node": ">=4.0" } }, - "node_modules/@esbuild/linux-s390x": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.1.tgz", - "integrity": "sha512-cEECeLlJNfT8kZHqLarDBQso9a27o2Zd2AQ8USAEoGtejOrCYHNtKP8XQhMDJMtthdF4GBmjR2au3x1udADQQQ==", - "cpu": [ - "s390x" - ], + "node_modules/estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "peer": true, - "engines": { - "node": ">=18" - } + "license": "MIT" }, - "node_modules/@esbuild/linux-x64": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.1.tgz", - "integrity": "sha512-xbfUhu/gnvSEg+EGovRc+kjBAkrvtk38RlerAzQxvMzlB4fXpCFCeUAYzJvrnhFtdeyVCDANSjJvOvGYoeKzFA==", - "cpu": [ - "x64" - ], + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "peer": true, + "license": "BSD-2-Clause", "engines": { - "node": ">=18" + "node": ">=0.10.0" } }, - "node_modules/@esbuild/netbsd-arm64": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.1.tgz", - "integrity": "sha512-O96poM2XGhLtpTh+s4+nP7YCCAfb4tJNRVZHfIE7dgmax+yMP2WgMd2OecBuaATHKTHsLWHQeuaxMRnCsH8+5g==", - "cpu": [ - "arm64" - ], + "node_modules/expect-type": { + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-0.15.0.tgz", + "integrity": "sha512-yWnriYB4e8G54M5/fAFj7rCIBiKs1HAACaY13kCz6Ku0dezjS9aMcfcdVK2X8Tv2tEV1BPz/wKfQ7WA4S/d8aA==", "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "peer": true, - "engines": { - "node": ">=18" - } + "license": "Apache-2.0" }, - "node_modules/@esbuild/netbsd-x64": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.1.tgz", - "integrity": "sha512-X53z6uXip6KFXBQ+Krbx25XHV/NCbzryM6ehOAeAil7X7oa4XIq+394PWGnwaSQ2WRA0KI6PUO6hTO5zeF5ijA==", - "cpu": [ - "x64" - ], + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "peer": true, - "engines": { - "node": ">=18" - } + "license": "MIT" }, - "node_modules/@esbuild/openbsd-arm64": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.1.tgz", - "integrity": "sha512-Na9T3szbXezdzM/Kfs3GcRQNjHzM6GzFBeU1/6IV/npKP5ORtp9zbQjvkDJ47s6BCgaAZnnnu/cY1x342+MvZg==", - "cpu": [ - "arm64" - ], + "node_modules/fast-glob": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", + "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "peer": true, - "engines": { - "node": ">=18" + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.8" + }, + "engines": { + "node": ">=8.6.0" } }, - "node_modules/@esbuild/openbsd-x64": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.1.tgz", - "integrity": "sha512-T3H78X2h1tszfRSf+txbt5aOp/e7TAz3ptVKu9Oyir3IAOFPGV6O9c2naym5TOriy1l0nNf6a4X5UXRZSGX/dw==", - "cpu": [ - "x64" - ], + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "peer": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, "engines": { - "node": ">=18" + "node": ">= 6" } }, - "node_modules/@esbuild/sunos-x64": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.1.tgz", - "integrity": "sha512-2H3RUvcmULO7dIE5EWJH8eubZAI4xw54H1ilJnRNZdeo8dTADEZ21w6J22XBkXqGJbe0+wnNJtw3UXRoLJnFEg==", - "cpu": [ - "x64" - ], + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "sunos" - ], - "peer": true, - "engines": { - "node": ">=18" - } + "license": "MIT" + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true, + "license": "MIT" }, - "node_modules/@esbuild/win32-arm64": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.1.tgz", - "integrity": "sha512-GE7XvrdOzrb+yVKB9KsRMq+7a2U/K5Cf/8grVFRAGJmfADr/e/ODQ134RK2/eeHqYV5eQRFxb1hY7Nr15fv1NQ==", - "cpu": [ - "arm64" + "node_modules/fast-uri": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.0.tgz", + "integrity": "sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } ], + "license": "BSD-3-Clause" + }, + "node_modules/fastest-levenshtein": { + "version": "1.0.16", + "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz", + "integrity": "sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "peer": true, "engines": { - "node": ">=18" + "node": ">= 4.9.1" } }, - "node_modules/@esbuild/win32-ia32": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.1.tgz", - "integrity": "sha512-uOxSJCIcavSiT6UnBhBzE8wy3n0hOkJsBOzy7HDAuTDE++1DJMRRVCPGisULScHL+a/ZwdXPpXD3IyFKjA7K8A==", - "cpu": [ - "ia32" - ], + "node_modules/fastq": { + "version": "1.19.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.1.tgz", + "integrity": "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==", "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "peer": true, - "engines": { - "node": ">=18" + "license": "ISC", + "dependencies": { + "reusify": "^1.0.4" } }, - "node_modules/@esbuild/win32-x64": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.1.tgz", - "integrity": "sha512-Y1EQdcfwMSeQN/ujR5VayLOJ1BHaK+ssyk0AEzPjC+t1lITgsnccPqFjb6V+LsTp/9Iov4ysfjxLaGJ9RPtkVg==", - "cpu": [ - "x64" - ], + "node_modules/file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "peer": true, + "dependencies": { + "flat-cache": "^3.0.4" + }, "engines": { - "node": ">=18" + "node": "^10.12.0 || >=12.0.0" } }, - "node_modules/@eslint-community/eslint-utils": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", - "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", "dev": true, + "license": "MIT", "dependencies": { - "eslint-visitor-keys": "^3.3.0" + "to-regex-range": "^5.0.1" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + "node": ">=8" } }, - "node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", - "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": ">=10" }, "funding": { - "url": "https://opencollective.com/eslint" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@eslint-community/regexpp": { - "version": "4.10.0", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.0.tgz", - "integrity": "sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==", + "node_modules/flat-cache": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", + "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", "dev": true, + "license": "MIT", + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.3", + "rimraf": "^3.0.2" + }, "engines": { - "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + "node": "^10.12.0 || >=12.0.0" } }, - "node_modules/@eslint/eslintrc": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", - "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", + "node_modules/flatted": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz", + "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==", + "dev": true, + "license": "ISC" + }, + "node_modules/for-each": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz", + "integrity": "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==", "dev": true, + "license": "MIT", "dependencies": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^9.6.0", - "globals": "^13.19.0", - "ignore": "^5.2.0", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "minimatch": "^3.1.2", - "strip-json-comments": "^3.1.1" + "is-callable": "^1.2.7" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": ">= 0.4" }, "funding": { - "url": "https://opencollective.com/eslint" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/@eslint/eslintrc/node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true, + "license": "ISC" }, - "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/@eslint/eslintrc/node_modules/globals": { - "version": "13.24.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", - "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "node_modules/function.prototype.name": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.8.tgz", + "integrity": "sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q==", "dev": true, + "license": "MIT", "dependencies": { - "type-fest": "^0.20.2" + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "functions-have-names": "^1.2.3", + "hasown": "^2.0.2", + "is-callable": "^1.2.7" }, "engines": { - "node": ">=8" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/@eslint/eslintrc/node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "node_modules/functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", "dev": true, - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/@eslint/eslintrc/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "node_modules/generator-function": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/generator-function/-/generator-function-2.0.1.tgz", + "integrity": "sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g==", "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, + "license": "MIT", "engines": { - "node": "*" + "node": ">= 0.4" } }, - "node_modules/@eslint/js": { - "version": "8.57.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.0.tgz", - "integrity": "sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==", + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/@humanwhocodes/config-array": { - "version": "0.11.14", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", - "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==", + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", "dev": true, + "license": "MIT", "dependencies": { - "@humanwhocodes/object-schema": "^2.0.2", - "debug": "^4.3.1", - "minimatch": "^3.0.5" + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" }, "engines": { - "node": ">=10.10.0" + "node": ">= 0.4" } }, - "node_modules/@humanwhocodes/config-array/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "node_modules/get-symbol-description": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.1.0.tgz", + "integrity": "sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==", "dev": true, + "license": "MIT", "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/@humanwhocodes/config-array/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", "dev": true, + "license": "ISC", "dependencies": { - "brace-expansion": "^1.1.7" + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" }, "engines": { "node": "*" - } - }, - "node_modules/@humanwhocodes/module-importer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", - "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", - "dev": true, - "engines": { - "node": ">=12.22" }, "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/@humanwhocodes/object-schema": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", - "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", - "dev": true - }, - "node_modules/@istanbuljs/load-nyc-config": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", - "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", "dev": true, + "license": "ISC", "dependencies": { - "camelcase": "^5.3.1", - "find-up": "^4.1.0", - "get-package-type": "^0.1.0", - "js-yaml": "^3.13.1", - "resolve-from": "^5.0.0" + "is-glob": "^4.0.3" }, "engines": { - "node": ">=8" + "node": ">=10.13.0" } }, - "node_modules/@istanbuljs/schema": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", - "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", + "node_modules/glob/node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", "dev": true, - "engines": { - "node": ">=8" + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" } }, - "node_modules/@jest/schemas": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", - "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", + "node_modules/glob/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, + "license": "ISC", "dependencies": { - "@sinclair/typebox": "^0.27.8" + "brace-expansion": "^1.1.7" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": "*" } }, - "node_modules/@jest/transform": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz", - "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==", + "node_modules/global-modules": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-2.0.0.tgz", + "integrity": "sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/core": "^7.11.6", - "@jest/types": "^29.6.3", - "@jridgewell/trace-mapping": "^0.3.18", - "babel-plugin-istanbul": "^6.1.1", - "chalk": "^4.0.0", - "convert-source-map": "^2.0.0", - "fast-json-stable-stringify": "^2.1.0", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.7.0", - "jest-regex-util": "^29.6.3", - "jest-util": "^29.7.0", - "micromatch": "^4.0.4", - "pirates": "^4.0.4", - "slash": "^3.0.0", - "write-file-atomic": "^4.0.2" + "global-prefix": "^3.0.0" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=6" } }, - "node_modules/@jest/transform/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "node_modules/global-prefix": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-3.0.0.tgz", + "integrity": "sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==", "dev": true, + "license": "MIT", "dependencies": { - "color-convert": "^2.0.1" + "ini": "^1.3.5", + "kind-of": "^6.0.2", + "which": "^1.3.1" }, "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "node": ">=6" } }, - "node_modules/@jest/transform/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "node_modules/global-prefix/node_modules/which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", "dev": true, + "license": "ISC", "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" + "isexe": "^2.0.0" }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "bin": { + "which": "bin/which" } }, - "node_modules/@jest/transform/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "node_modules/globals": { + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", "dev": true, + "license": "MIT", "dependencies": { - "color-name": "~1.1.4" + "type-fest": "^0.20.2" }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/@jest/transform/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/@jest/transform/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, "engines": { "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@jest/transform/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "node_modules/globalthis": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", + "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", "dev": true, + "license": "MIT", "dependencies": { - "has-flag": "^4.0.0" + "define-properties": "^1.2.1", + "gopd": "^1.0.1" }, "engines": { - "node": ">=8" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/@jest/types": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", - "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", + "node_modules/globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", "dev": true, + "license": "MIT", "dependencies": { - "@jest/schemas": "^29.6.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^17.0.8", - "chalk": "^4.0.0" + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@jest/types/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "node_modules/globjoin": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/globjoin/-/globjoin-0.1.4.tgz", + "integrity": "sha512-xYfnw62CKG8nLkZBfWbhWwDw02CHty86jfPcc2cr3ZfeuK9ysoVPPEUxf21bAD/rWAgk52SuBrLJlefNy8mvFg==", "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, + "license": "MIT" + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "dev": true, + "license": "MIT", "engines": { - "node": ">=8" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/@jest/types/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "node_modules/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, + "license": "MIT" + }, + "node_modules/hard-rejection": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/hard-rejection/-/hard-rejection-2.1.0.tgz", + "integrity": "sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==", + "dev": true, + "license": "MIT", "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "node": ">=6" } }, - "node_modules/@jest/types/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "node_modules/has": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.4.tgz", + "integrity": "sha512-qdSAmqLF6209RFj4VVItywPMbm3vWylknmB3nvNiUIs72xAimcM8nVYxYr7ncvZq5qzk9MKIZR8ijqD/1QuYjQ==", "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, + "license": "MIT", "engines": { - "node": ">=7.0.0" + "node": ">= 0.4.0" } }, - "node_modules/@jest/types/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true + "node_modules/has-bigints": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.1.0.tgz", + "integrity": "sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, - "node_modules/@jest/types/node_modules/has-flag": { + "node_modules/has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, - "node_modules/@jest/types/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "node_modules/has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", "dev": true, + "license": "MIT", "dependencies": { - "has-flag": "^4.0.0" + "es-define-property": "^1.0.0" }, - "engines": { - "node": ">=8" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", - "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", + "node_modules/has-proto": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.2.0.tgz", + "integrity": "sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==", "dev": true, + "license": "MIT", "dependencies": { - "@jridgewell/set-array": "^1.2.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.24" + "dunder-proto": "^1.0.0" }, "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", - "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", - "dev": true, - "engines": { - "node": ">=6.0.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/@jridgewell/set-array": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", - "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", "dev": true, + "license": "MIT", "engines": { - "node": ">=6.0.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/@jridgewell/source-map": { - "version": "0.3.6", - "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.6.tgz", - "integrity": "sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==", + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", "dev": true, - "peer": true, + "license": "MIT", "dependencies": { - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.25" - } - }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", - "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.25", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", - "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", - "dev": true, - "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" - } - }, - "node_modules/@keyv/serialize": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@keyv/serialize/-/serialize-1.0.3.tgz", - "integrity": "sha512-qnEovoOp5Np2JDGonIDL6Ayihw0RhnRh6vxPuHo4RDn1UOzwEo4AeIfpL6UGIrsceWrCMiVPgwRjbHu4vYFc3g==", - "dev": true, - "license": "MIT", - "dependencies": { - "buffer": "^6.0.3" - } - }, - "node_modules/@keyv/serialize/node_modules/buffer": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", - "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT", - "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.2.1" - } - }, - "node_modules/@nicolo-ribaudo/eslint-scope-5-internals": { - "version": "5.1.1-v1", - "resolved": "https://registry.npmjs.org/@nicolo-ribaudo/eslint-scope-5-internals/-/eslint-scope-5-internals-5.1.1-v1.tgz", - "integrity": "sha512-54/JRvkLIzzDWshCWfuhadfrfZVPiElY8Fcgmg1HroEly/EDSszzhBAsarCux+D/kOslTRquNzuyGSmUSTTHGg==", - "dev": true, - "dependencies": { - "eslint-scope": "5.1.1" - } - }, - "node_modules/@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "dev": true, - "dependencies": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "dev": true, - "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.37.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.37.0.tgz", - "integrity": "sha512-l7StVw6WAa8l3vA1ov80jyetOAEo1FtHvZDbzXDO/02Sq/QVvqlHkYoFwDJPIMj0GKiistsBudfx5tGFnwYWDQ==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "peer": true - }, - "node_modules/@rollup/rollup-android-arm64": { - "version": "4.37.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.37.0.tgz", - "integrity": "sha512-6U3SlVyMxezt8Y+/iEBcbp945uZjJwjZimu76xoG7tO1av9VO691z8PkhzQ85ith2I8R2RddEPeSfcbyPfD4hA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "peer": true - }, - "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.37.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.37.0.tgz", - "integrity": "sha512-+iTQ5YHuGmPt10NTzEyMPbayiNTcOZDWsbxZYR1ZnmLnZxG17ivrPSWFO9j6GalY0+gV3Jtwrrs12DBscxnlYA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "peer": true - }, - "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.37.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.37.0.tgz", - "integrity": "sha512-m8W2UbxLDcmRKVjgl5J/k4B8d7qX2EcJve3Sut7YGrQoPtCIQGPH5AMzuFvYRWZi0FVS0zEY4c8uttPfX6bwYQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "peer": true - }, - "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.37.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.37.0.tgz", - "integrity": "sha512-FOMXGmH15OmtQWEt174v9P1JqqhlgYge/bUjIbiVD1nI1NeJ30HYT9SJlZMqdo1uQFyt9cz748F1BHghWaDnVA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "peer": true - }, - "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.37.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.37.0.tgz", - "integrity": "sha512-SZMxNttjPKvV14Hjck5t70xS3l63sbVwl98g3FlVVx2YIDmfUIy29jQrsw06ewEYQ8lQSuY9mpAPlmgRD2iSsA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "peer": true - }, - "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.37.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.37.0.tgz", - "integrity": "sha512-hhAALKJPidCwZcj+g+iN+38SIOkhK2a9bqtJR+EtyxrKKSt1ynCBeqrQy31z0oWU6thRZzdx53hVgEbRkuI19w==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "peer": true - }, - "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.37.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.37.0.tgz", - "integrity": "sha512-jUb/kmn/Gd8epbHKEqkRAxq5c2EwRt0DqhSGWjPFxLeFvldFdHQs/n8lQ9x85oAeVb6bHcS8irhTJX2FCOd8Ag==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "peer": true - }, - "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.37.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.37.0.tgz", - "integrity": "sha512-oNrJxcQT9IcbcmKlkF+Yz2tmOxZgG9D9GRq+1OE6XCQwCVwxixYAa38Z8qqPzQvzt1FCfmrHX03E0pWoXm1DqA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "peer": true - }, - "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.37.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.37.0.tgz", - "integrity": "sha512-pfxLBMls+28Ey2enpX3JvjEjaJMBX5XlPCZNGxj4kdJyHduPBXtxYeb8alo0a7bqOoWZW2uKynhHxF/MWoHaGQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "peer": true - }, - "node_modules/@rollup/rollup-linux-loongarch64-gnu": { - "version": "4.37.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.37.0.tgz", - "integrity": "sha512-yCE0NnutTC/7IGUq/PUHmoeZbIwq3KRh02e9SfFh7Vmc1Z7atuJRYWhRME5fKgT8aS20mwi1RyChA23qSyRGpA==", - "cpu": [ - "loong64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "peer": true - }, - "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { - "version": "4.37.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.37.0.tgz", - "integrity": "sha512-NxcICptHk06E2Lh3a4Pu+2PEdZ6ahNHuK7o6Np9zcWkrBMuv21j10SQDJW3C9Yf/A/P7cutWoC/DptNLVsZ0VQ==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "peer": true - }, - "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.37.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.37.0.tgz", - "integrity": "sha512-PpWwHMPCVpFZLTfLq7EWJWvrmEuLdGn1GMYcm5MV7PaRgwCEYJAwiN94uBuZev0/J/hFIIJCsYw4nLmXA9J7Pw==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "peer": true - }, - "node_modules/@rollup/rollup-linux-riscv64-musl": { - "version": "4.37.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.37.0.tgz", - "integrity": "sha512-DTNwl6a3CfhGTAOYZ4KtYbdS8b+275LSLqJVJIrPa5/JuIufWWZ/QFvkxp52gpmguN95eujrM68ZG+zVxa8zHA==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "peer": true - }, - "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.37.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.37.0.tgz", - "integrity": "sha512-hZDDU5fgWvDdHFuExN1gBOhCuzo/8TMpidfOR+1cPZJflcEzXdCy1LjnklQdW8/Et9sryOPJAKAQRw8Jq7Tg+A==", - "cpu": [ - "s390x" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "peer": true - }, - "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.37.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.37.0.tgz", - "integrity": "sha512-pKivGpgJM5g8dwj0ywBwe/HeVAUSuVVJhUTa/URXjxvoyTT/AxsLTAbkHkDHG7qQxLoW2s3apEIl26uUe08LVQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "peer": true - }, - "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.37.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.37.0.tgz", - "integrity": "sha512-E2lPrLKE8sQbY/2bEkVTGDEk4/49UYRVWgj90MY8yPjpnGBQ+Xi1Qnr7b7UIWw1NOggdFQFOLZ8+5CzCiz143w==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "peer": true - }, - "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.37.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.37.0.tgz", - "integrity": "sha512-Jm7biMazjNzTU4PrQtr7VS8ibeys9Pn29/1bm4ph7CP2kf21950LgN+BaE2mJ1QujnvOc6p54eWWiVvn05SOBg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "peer": true - }, - "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.37.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.37.0.tgz", - "integrity": "sha512-e3/1SFm1OjefWICB2Ucstg2dxYDkDTZGDYgwufcbsxTHyqQps1UQf33dFEChBNmeSsTOyrjw2JJq0zbG5GF6RA==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "peer": true - }, - "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.37.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.37.0.tgz", - "integrity": "sha512-LWbXUBwn/bcLx2sSsqy7pK5o+Nr+VCoRoAohfJ5C/aBio9nfJmGQqHAhU6pwxV/RmyTk5AqdySma7uwWGlmeuA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "peer": true - }, - "node_modules/@shopware-ag/eslint-config-base": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@shopware-ag/eslint-config-base/-/eslint-config-base-2.0.0.tgz", - "integrity": "sha512-G7VOfkg9SsybDfCohUB+YRcn/yaTzxQfNLfNdmvE03BK7kh0f2edwUu64FfQKMcRzVmL8lvu/sl4oErTJsNsQA==", - "dev": true, - "dependencies": { - "eslint": "^8.29.0", - "eslint-config-airbnb-base": "^15.0.0", - "eslint-plugin-import": "2.26.0" - } - }, - "node_modules/@shopware-ag/eslint-config-base/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/@shopware-ag/eslint-config-base/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/@shopware-ag/eslint-config-base/node_modules/doctrine": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", - "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", - "dev": true, - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/@shopware-ag/eslint-config-base/node_modules/eslint-plugin-import": { - "version": "2.26.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.26.0.tgz", - "integrity": "sha512-hYfi3FXaM8WPLf4S1cikh/r4IxnO6zrhZbEGz2b660EJRbuxgpDS5gkCuYgGWg2xxh2rBuIr4Pvhve/7c31koA==", - "dev": true, - "dependencies": { - "array-includes": "^3.1.4", - "array.prototype.flat": "^1.2.5", - "debug": "^2.6.9", - "doctrine": "^2.1.0", - "eslint-import-resolver-node": "^0.3.6", - "eslint-module-utils": "^2.7.3", - "has": "^1.0.3", - "is-core-module": "^2.8.1", - "is-glob": "^4.0.3", - "minimatch": "^3.1.2", - "object.values": "^1.1.5", - "resolve": "^1.22.0", - "tsconfig-paths": "^3.14.1" - }, - "engines": { - "node": ">=4" - }, - "peerDependencies": { - "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8" - } - }, - "node_modules/@shopware-ag/eslint-config-base/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/@shopware-ag/eslint-config-base/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true - }, - "node_modules/@shopware-ag/meteor-tokens": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@shopware-ag/meteor-tokens/-/meteor-tokens-1.0.0.tgz", - "integrity": "sha512-MdxJdmbHvrGdesuXuIfU2NujryaU+HByuf5FMIgK2xJ7dTWzQZWAj/+mR5Pt9+mOQTP9Gy/pBtoAzznT5/wrug==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "dotenv": "^16.4.7", - "ora": "^8.2.0", - "vitest": "^3.0.6", - "zod": "^3.24.2" - } - }, - "node_modules/@shopware-ag/meteor-tokens/node_modules/ansi-regex": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", - "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/@shopware-ag/meteor-tokens/node_modules/chalk": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.4.1.tgz", - "integrity": "sha512-zgVZuo2WcZgfUEmsn6eO3kINexW8RAE4maiQ8QNs8CtpPCSyMiYsULR3HQYkm3w8FIA3SberyMJMSldGsW+U3w==", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": "^12.17.0 || ^14.13 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/@shopware-ag/meteor-tokens/node_modules/cli-cursor": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-5.0.0.tgz", - "integrity": "sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "restore-cursor": "^5.0.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@shopware-ag/meteor-tokens/node_modules/is-interactive": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-2.0.0.tgz", - "integrity": "sha512-qP1vozQRI+BMOPcjFzrjXuQvdak2pHNUMZoeG2eRbiSqyvbEf/wQtEOTOX1guk6E3t36RkaqiSt8A/6YElNxLQ==", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@shopware-ag/meteor-tokens/node_modules/is-unicode-supported": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-2.1.0.tgz", - "integrity": "sha512-mE00Gnza5EEB3Ds0HfMyllZzbBrmLOX3vfWoj9A9PEnTfratQ/BcaJOuMhnkhjXvb2+FkY3VuHqtAGpTPmglFQ==", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@shopware-ag/meteor-tokens/node_modules/log-symbols": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-6.0.0.tgz", - "integrity": "sha512-i24m8rpwhmPIS4zscNzK6MSEhk0DUWa/8iYQWxhffV8jkI4Phvs3F+quL5xvS0gdQR0FyTCMMH33Y78dDTzzIw==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "chalk": "^5.3.0", - "is-unicode-supported": "^1.3.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@shopware-ag/meteor-tokens/node_modules/log-symbols/node_modules/is-unicode-supported": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-1.3.0.tgz", - "integrity": "sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@shopware-ag/meteor-tokens/node_modules/onetime": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-7.0.0.tgz", - "integrity": "sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "mimic-function": "^5.0.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@shopware-ag/meteor-tokens/node_modules/ora": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/ora/-/ora-8.2.0.tgz", - "integrity": "sha512-weP+BZ8MVNnlCm8c0Qdc1WSWq4Qn7I+9CJGm7Qali6g44e/PUzbjNqJX5NJ9ljlNMosfJvg1fKEGILklK9cwnw==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "chalk": "^5.3.0", - "cli-cursor": "^5.0.0", - "cli-spinners": "^2.9.2", - "is-interactive": "^2.0.0", - "is-unicode-supported": "^2.0.0", - "log-symbols": "^6.0.0", - "stdin-discarder": "^0.2.2", - "string-width": "^7.2.0", - "strip-ansi": "^7.1.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@shopware-ag/meteor-tokens/node_modules/restore-cursor": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-5.1.0.tgz", - "integrity": "sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "onetime": "^7.0.0", - "signal-exit": "^4.1.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@shopware-ag/meteor-tokens/node_modules/signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", - "dev": true, - "license": "ISC", - "peer": true, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/@shopware-ag/meteor-tokens/node_modules/string-width": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", - "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "emoji-regex": "^10.3.0", - "get-east-asian-width": "^1.0.0", - "strip-ansi": "^7.1.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@shopware-ag/meteor-tokens/node_modules/strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "ansi-regex": "^6.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, - "node_modules/@shopware-ag/stylelint-plugin-meteor": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@shopware-ag/stylelint-plugin-meteor/-/stylelint-plugin-meteor-1.1.0.tgz", - "integrity": "sha512-x55+bznbjwWd4B3GEtfnY7ORQTyY2/XLaot2GP6+O0AW26pCylD+MnVm0KwkW8qujCnvnl0tKWGKHn8c6jmeVA==", - "dev": true, - "license": "MIT", - "peerDependencies": { - "@shopware-ag/meteor-tokens": "1.0.0", - "stylelint": "^16.10.0" - } - }, - "node_modules/@sinclair/typebox": { - "version": "0.27.8", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", - "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", - "dev": true - }, - "node_modules/@types/babel__core": { - "version": "7.20.5", - "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", - "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", - "dev": true, - "dependencies": { - "@babel/parser": "^7.20.7", - "@babel/types": "^7.20.7", - "@types/babel__generator": "*", - "@types/babel__template": "*", - "@types/babel__traverse": "*" - } - }, - "node_modules/@types/babel__generator": { - "version": "7.6.8", - "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.8.tgz", - "integrity": "sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==", - "dev": true, - "dependencies": { - "@babel/types": "^7.0.0" - } - }, - "node_modules/@types/babel__template": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", - "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", - "dev": true, - "dependencies": { - "@babel/parser": "^7.1.0", - "@babel/types": "^7.0.0" - } - }, - "node_modules/@types/babel__traverse": { - "version": "7.20.5", - "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.5.tgz", - "integrity": "sha512-WXCyOcRtH37HAUkpXhUduaxdm82b4GSlyTqajXviN4EfiuPgNYR109xMCKvpl6zPIpua0DGlMEDCq+g8EdoheQ==", - "dev": true, - "dependencies": { - "@babel/types": "^7.20.7" - } - }, - "node_modules/@types/eslint": { - "version": "8.56.10", - "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.56.10.tgz", - "integrity": "sha512-Shavhk87gCtY2fhXDctcfS3e6FdxWkCx1iUZ9eEUbh7rTqlZT0/IzOkCOVt0fCjcFuZ9FPYfuezTBImfHCDBGQ==", - "dev": true, - "peer": true, - "dependencies": { - "@types/estree": "*", - "@types/json-schema": "*" - } - }, - "node_modules/@types/eslint-scope": { - "version": "3.7.7", - "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.7.tgz", - "integrity": "sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==", - "dev": true, - "peer": true, - "dependencies": { - "@types/eslint": "*", - "@types/estree": "*" - } - }, - "node_modules/@types/estree": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", - "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", - "dev": true, - "license": "MIT", - "peer": true - }, - "node_modules/@types/graceful-fs": { - "version": "4.1.9", - "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.9.tgz", - "integrity": "sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/istanbul-lib-coverage": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz", - "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==", - "dev": true - }, - "node_modules/@types/istanbul-lib-report": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz", - "integrity": "sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==", - "dev": true, - "dependencies": { - "@types/istanbul-lib-coverage": "*" - } - }, - "node_modules/@types/istanbul-reports": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz", - "integrity": "sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==", - "dev": true, - "dependencies": { - "@types/istanbul-lib-report": "*" - } - }, - "node_modules/@types/json-schema": { - "version": "7.0.15", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", - "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", - "dev": true, - "peer": true - }, - "node_modules/@types/json5": { - "version": "0.0.29", - "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", - "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", - "dev": true - }, - "node_modules/@types/node": { - "version": "20.12.12", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.12.tgz", - "integrity": "sha512-eWLDGF/FOSPtAvEqeRAQ4C8LSA7M1I7i0ky1I8U7kD1J5ITyW3AsRhQrKVoWf5pFKZ2kILsEGJhsI9r93PYnOw==", - "dev": true, - "dependencies": { - "undici-types": "~5.26.4" - } - }, - "node_modules/@types/yargs": { - "version": "17.0.32", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.32.tgz", - "integrity": "sha512-xQ67Yc/laOG5uMfX/093MRlGGCIBzZMarVa+gfNKJxWAIgykYpVGkBdbqEzGDDfCrVUj6Hiff4mTZ5BA6TmAog==", - "dev": true, - "dependencies": { - "@types/yargs-parser": "*" - } - }, - "node_modules/@types/yargs-parser": { - "version": "21.0.3", - "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz", - "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==", - "dev": true - }, - "node_modules/@typescript-eslint/eslint-plugin": { - "version": "7.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.9.0.tgz", - "integrity": "sha512-6e+X0X3sFe/G/54aC3jt0txuMTURqLyekmEHViqyA2VnxhLMpvA6nqmcjIy+Cr9tLDHPssA74BP5Mx9HQIxBEA==", - "dev": true, - "dependencies": { - "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "7.9.0", - "@typescript-eslint/type-utils": "7.9.0", - "@typescript-eslint/utils": "7.9.0", - "@typescript-eslint/visitor-keys": "7.9.0", - "graphemer": "^1.4.0", - "ignore": "^5.3.1", - "natural-compare": "^1.4.0", - "ts-api-utils": "^1.3.0" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "@typescript-eslint/parser": "^7.0.0", - "eslint": "^8.56.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/parser": { - "version": "7.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.9.0.tgz", - "integrity": "sha512-qHMJfkL5qvgQB2aLvhUSXxbK7OLnDkwPzFalg458pxQgfxKDfT1ZDbHQM/I6mDIf/svlMkj21kzKuQ2ixJlatQ==", - "dev": true, - "dependencies": { - "@typescript-eslint/scope-manager": "7.9.0", - "@typescript-eslint/types": "7.9.0", - "@typescript-eslint/typescript-estree": "7.9.0", - "@typescript-eslint/visitor-keys": "7.9.0", - "debug": "^4.3.4" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.56.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/scope-manager": { - "version": "7.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.9.0.tgz", - "integrity": "sha512-ZwPK4DeCDxr3GJltRz5iZejPFAAr4Wk3+2WIBaj1L5PYK5RgxExu/Y68FFVclN0y6GGwH8q+KgKRCvaTmFBbgQ==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "7.9.0", - "@typescript-eslint/visitor-keys": "7.9.0" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/type-utils": { - "version": "7.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.9.0.tgz", - "integrity": "sha512-6Qy8dfut0PFrFRAZsGzuLoM4hre4gjzWJB6sUvdunCYZsYemTkzZNwF1rnGea326PHPT3zn5Lmg32M/xfJfByA==", - "dev": true, - "dependencies": { - "@typescript-eslint/typescript-estree": "7.9.0", - "@typescript-eslint/utils": "7.9.0", - "debug": "^4.3.4", - "ts-api-utils": "^1.3.0" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.56.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/types": { - "version": "7.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.9.0.tgz", - "integrity": "sha512-oZQD9HEWQanl9UfsbGVcZ2cGaR0YT5476xfWE0oE5kQa2sNK2frxOlkeacLOTh9po4AlUT5rtkGyYM5kew0z5w==", - "dev": true, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/typescript-estree": { - "version": "7.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.9.0.tgz", - "integrity": "sha512-zBCMCkrb2YjpKV3LA0ZJubtKCDxLttxfdGmwZvTqqWevUPN0FZvSI26FalGFFUZU/9YQK/A4xcQF9o/VVaCKAg==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "7.9.0", - "@typescript-eslint/visitor-keys": "7.9.0", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "minimatch": "^9.0.4", - "semver": "^7.6.0", - "ts-api-utils": "^1.3.0" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": { - "version": "7.6.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", - "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@typescript-eslint/utils": { - "version": "7.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.9.0.tgz", - "integrity": "sha512-5KVRQCzZajmT4Ep+NEgjXCvjuypVvYHUW7RHlXzNPuak2oWpVoD1jf5xCP0dPAuNIchjC7uQyvbdaSTFaLqSdA==", - "dev": true, - "dependencies": { - "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "7.9.0", - "@typescript-eslint/types": "7.9.0", - "@typescript-eslint/typescript-estree": "7.9.0" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.56.0" - } - }, - "node_modules/@typescript-eslint/visitor-keys": { - "version": "7.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.9.0.tgz", - "integrity": "sha512-iESPx2TNLDNGQLyjKhUvIKprlP49XNEK+MvIf9nIO7ZZaZdbnfWKHnXAgufpxqfA0YryH8XToi4+CjBgVnFTSQ==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "7.9.0", - "eslint-visitor-keys": "^3.4.3" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", - "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", - "dev": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/@ungap/structured-clone": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", - "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", - "dev": true - }, - "node_modules/@vitest/expect": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-3.0.9.tgz", - "integrity": "sha512-5eCqRItYgIML7NNVgJj6TVCmdzE7ZVgJhruW0ziSQV4V7PvLkDL1bBkBdcTs/VuIz0IxPb5da1IDSqc1TR9eig==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@vitest/spy": "3.0.9", - "@vitest/utils": "3.0.9", - "chai": "^5.2.0", - "tinyrainbow": "^2.0.0" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/@vitest/mocker": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-3.0.9.tgz", - "integrity": "sha512-ryERPIBOnvevAkTq+L1lD+DTFBRcjueL9lOUfXsLfwP92h4e+Heb+PjiqS3/OURWPtywfafK0kj++yDFjWUmrA==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@vitest/spy": "3.0.9", - "estree-walker": "^3.0.3", - "magic-string": "^0.30.17" - }, - "funding": { - "url": "https://opencollective.com/vitest" - }, - "peerDependencies": { - "msw": "^2.4.9", - "vite": "^5.0.0 || ^6.0.0" - }, - "peerDependenciesMeta": { - "msw": { - "optional": true - }, - "vite": { - "optional": true - } - } - }, - "node_modules/@vitest/pretty-format": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-3.0.9.tgz", - "integrity": "sha512-OW9F8t2J3AwFEwENg3yMyKWweF7oRJlMyHOMIhO5F3n0+cgQAJZBjNgrF8dLwFTEXl5jUqBLXd9QyyKv8zEcmA==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "tinyrainbow": "^2.0.0" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/@vitest/runner": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-3.0.9.tgz", - "integrity": "sha512-NX9oUXgF9HPfJSwl8tUZCMP1oGx2+Sf+ru6d05QjzQz4OwWg0psEzwY6VexP2tTHWdOkhKHUIZH+fS6nA7jfOw==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@vitest/utils": "3.0.9", - "pathe": "^2.0.3" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/@vitest/snapshot": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-3.0.9.tgz", - "integrity": "sha512-AiLUiuZ0FuA+/8i19mTYd+re5jqjEc2jZbgJ2up0VY0Ddyyxg/uUtBDpIFAy4uzKaQxOW8gMgBdAJJ2ydhu39A==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@vitest/pretty-format": "3.0.9", - "magic-string": "^0.30.17", - "pathe": "^2.0.3" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/@vitest/spy": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-3.0.9.tgz", - "integrity": "sha512-/CcK2UDl0aQ2wtkp3YVWldrpLRNCfVcIOFGlVGKO4R5eajsH393Z1yiXLVQ7vWsj26JOEjeZI0x5sm5P4OGUNQ==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "tinyspy": "^3.0.2" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/@vitest/utils": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-3.0.9.tgz", - "integrity": "sha512-ilHM5fHhZ89MCp5aAaM9uhfl1c2JdxVxl3McqsdVyVNN6JffnEen8UMCdRTzOhGXNQGo5GNL9QugHrz727Wnng==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@vitest/pretty-format": "3.0.9", - "loupe": "^3.1.3", - "tinyrainbow": "^2.0.0" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/@webassemblyjs/ast": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.12.1.tgz", - "integrity": "sha512-EKfMUOPRRUTy5UII4qJDGPpqfwjOmZ5jeGFwid9mnoqIFK+e0vqoi1qH56JpmZSzEL53jKnNzScdmftJyG5xWg==", - "dev": true, - "peer": true, - "dependencies": { - "@webassemblyjs/helper-numbers": "1.11.6", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6" - } - }, - "node_modules/@webassemblyjs/floating-point-hex-parser": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz", - "integrity": "sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==", - "dev": true, - "peer": true - }, - "node_modules/@webassemblyjs/helper-api-error": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz", - "integrity": "sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==", - "dev": true, - "peer": true - }, - "node_modules/@webassemblyjs/helper-buffer": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.12.1.tgz", - "integrity": "sha512-nzJwQw99DNDKr9BVCOZcLuJJUlqkJh+kVzVl6Fmq/tI5ZtEyWT1KZMyOXltXLZJmDtvLCDgwsyrkohEtopTXCw==", - "dev": true, - "peer": true - }, - "node_modules/@webassemblyjs/helper-numbers": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz", - "integrity": "sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g==", - "dev": true, - "peer": true, - "dependencies": { - "@webassemblyjs/floating-point-hex-parser": "1.11.6", - "@webassemblyjs/helper-api-error": "1.11.6", - "@xtuc/long": "4.2.2" - } - }, - "node_modules/@webassemblyjs/helper-wasm-bytecode": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz", - "integrity": "sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==", - "dev": true, - "peer": true - }, - "node_modules/@webassemblyjs/helper-wasm-section": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.12.1.tgz", - "integrity": "sha512-Jif4vfB6FJlUlSbgEMHUyk1j234GTNG9dBJ4XJdOySoj518Xj0oGsNi59cUQF4RRMS9ouBUxDDdyBVfPTypa5g==", - "dev": true, - "peer": true, - "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" - } - }, - "node_modules/@webassemblyjs/ieee754": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz", - "integrity": "sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==", - "dev": true, - "peer": true, - "dependencies": { - "@xtuc/ieee754": "^1.2.0" - } - }, - "node_modules/@webassemblyjs/leb128": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.6.tgz", - "integrity": "sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==", - "dev": true, - "peer": true, - "dependencies": { - "@xtuc/long": "4.2.2" - } - }, - "node_modules/@webassemblyjs/utf8": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.6.tgz", - "integrity": "sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==", - "dev": true, - "peer": true - }, - "node_modules/@webassemblyjs/wasm-edit": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.12.1.tgz", - "integrity": "sha512-1DuwbVvADvS5mGnXbE+c9NfA8QRcZ6iKquqjjmR10k6o+zzsRVesil54DKexiowcFCPdr/Q0qaMgB01+SQ1u6g==", - "dev": true, - "peer": true, - "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" - } - }, - "node_modules/@webassemblyjs/wasm-gen": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.12.1.tgz", - "integrity": "sha512-TDq4Ojh9fcohAw6OIMXqiIcTq5KUXTGRkVxbSo1hQnSy6lAM5GSdfwWeSxpAo0YzgsgF182E/U0mDNhuA0tW7w==", - "dev": true, - "peer": true, - "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" - } - }, - "node_modules/@webassemblyjs/wasm-opt": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.12.1.tgz", - "integrity": "sha512-Jg99j/2gG2iaz3hijw857AVYekZe2SAskcqlWIZXjji5WStnOpVoat3gQfT/Q5tb2djnCjBtMocY/Su1GfxPBg==", - "dev": true, - "peer": true, - "dependencies": { - "@webassemblyjs/ast": "1.12.1", - "@webassemblyjs/helper-buffer": "1.12.1", - "@webassemblyjs/wasm-gen": "1.12.1", - "@webassemblyjs/wasm-parser": "1.12.1" - } - }, - "node_modules/@webassemblyjs/wasm-parser": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.12.1.tgz", - "integrity": "sha512-xikIi7c2FHXysxXe3COrVUPSheuBtpcfhbpFj4gmu7KRLYOzANztwUU0IbsqvMqzuNK2+glRGWCEqZo1WCLyAQ==", - "dev": true, - "peer": true, - "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" - } - }, - "node_modules/@webassemblyjs/wast-printer": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.12.1.tgz", - "integrity": "sha512-+X4WAlOisVWQMikjbcvY2e0rwPsKQ9F688lksZhBcPycBBuii3O7m8FACbDMWDojpAqvjIncrG8J0XHKyQfVeA==", - "dev": true, - "peer": true, - "dependencies": { - "@webassemblyjs/ast": "1.12.1", - "@xtuc/long": "4.2.2" - } - }, - "node_modules/@xtuc/ieee754": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", - "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", - "dev": true, - "peer": true - }, - "node_modules/@xtuc/long": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", - "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", - "dev": true, - "peer": true - }, - "node_modules/acorn": { - "version": "8.11.3", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", - "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==", - "dev": true, - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/acorn-import-assertions": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.9.0.tgz", - "integrity": "sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA==", - "dev": true, - "peer": true, - "peerDependencies": { - "acorn": "^8" - } - }, - "node_modules/acorn-jsx": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", - "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "dev": true, - "peerDependencies": { - "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" - } - }, - "node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/ajv-keywords": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", - "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", - "dev": true, - "peer": true, - "peerDependencies": { - "ajv": "^6.9.1" - } - }, - "node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/anymatch": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", - "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", - "dev": true, - "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "dependencies": { - "sprintf-js": "~1.0.2" - } - }, - "node_modules/aria-query": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.0.tgz", - "integrity": "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==", - "dev": true, - "dependencies": { - "dequal": "^2.0.3" - } - }, - "node_modules/array-buffer-byte-length": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz", - "integrity": "sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.5", - "is-array-buffer": "^3.0.4" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array-includes": { - "version": "3.1.8", - "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.8.tgz", - "integrity": "sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.2", - "es-object-atoms": "^1.0.0", - "get-intrinsic": "^1.2.4", - "is-string": "^1.0.7" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array-union": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/array.prototype.find": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/array.prototype.find/-/array.prototype.find-2.2.3.tgz", - "integrity": "sha512-fO/ORdOELvjbbeIfZfzrXFMhYHGofRGqd+am9zm3tZ4GlJINj/pA2eITyfd65Vg6+ZbHd/Cys7stpoRSWtQFdA==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.2", - "es-object-atoms": "^1.0.0", - "es-shim-unscopables": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array.prototype.findlastindex": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.5.tgz", - "integrity": "sha512-zfETvRFA8o7EiNn++N5f/kaCw221hrpGsDmcpndVupkPzEc1Wuf3VgC0qby1BbHs7f5DVYjgtEU2LLh5bqeGfQ==", - "dev": true, - "peer": true, - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.2", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.0.0", - "es-shim-unscopables": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array.prototype.flat": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz", - "integrity": "sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "es-shim-unscopables": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array.prototype.flatmap": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.2.tgz", - "integrity": "sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==", - "dev": true, - "peer": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "es-shim-unscopables": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/arraybuffer.prototype.slice": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.3.tgz", - "integrity": "sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==", - "dev": true, - "dependencies": { - "array-buffer-byte-length": "^1.0.1", - "call-bind": "^1.0.5", - "define-properties": "^1.2.1", - "es-abstract": "^1.22.3", - "es-errors": "^1.2.1", - "get-intrinsic": "^1.2.3", - "is-array-buffer": "^3.0.4", - "is-shared-array-buffer": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/assertion-error": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz", - "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/astral-regex": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", - "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/available-typed-arrays": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", - "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", - "dev": true, - "dependencies": { - "possible-typed-array-names": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/babel-jest": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz", - "integrity": "sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==", - "dev": true, - "dependencies": { - "@jest/transform": "^29.7.0", - "@types/babel__core": "^7.1.14", - "babel-plugin-istanbul": "^6.1.1", - "babel-preset-jest": "^29.6.3", - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "slash": "^3.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "@babel/core": "^7.8.0" - } - }, - "node_modules/babel-jest/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/babel-jest/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/babel-jest/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/babel-jest/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/babel-jest/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/babel-jest/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/babel-plugin-istanbul": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", - "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.0.0", - "@istanbuljs/load-nyc-config": "^1.0.0", - "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-instrument": "^5.0.4", - "test-exclude": "^6.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/babel-plugin-jest-hoist": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz", - "integrity": "sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==", - "dev": true, - "dependencies": { - "@babel/template": "^7.3.3", - "@babel/types": "^7.3.3", - "@types/babel__core": "^7.1.14", - "@types/babel__traverse": "^7.0.6" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/babel-plugin-module-resolver": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/babel-plugin-module-resolver/-/babel-plugin-module-resolver-5.0.2.tgz", - "integrity": "sha512-9KtaCazHee2xc0ibfqsDeamwDps6FZNo5S0Q81dUqEuFzVwPhcT4J5jOqIVvgCA3Q/wO9hKYxN/Ds3tIsp5ygg==", - "dev": true, - "dependencies": { - "find-babel-config": "^2.1.1", - "glob": "^9.3.3", - "pkg-up": "^3.1.0", - "reselect": "^4.1.7", - "resolve": "^1.22.8" - } - }, - "node_modules/babel-plugin-polyfill-corejs2": { - "version": "0.4.11", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.11.tgz", - "integrity": "sha512-sMEJ27L0gRHShOh5G54uAAPaiCOygY/5ratXuiyb2G46FmlSpc9eFCzYVyDiPxfNbwzA7mYahmjQc5q+CZQ09Q==", - "dev": true, - "dependencies": { - "@babel/compat-data": "^7.22.6", - "@babel/helper-define-polyfill-provider": "^0.6.2", - "semver": "^6.3.1" - }, - "peerDependencies": { - "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" - } - }, - "node_modules/babel-plugin-polyfill-corejs3": { - "version": "0.10.4", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.10.4.tgz", - "integrity": "sha512-25J6I8NGfa5YkCDogHRID3fVCadIR8/pGl1/spvCkzb6lVn6SR3ojpx9nOn9iEBcUsjY24AmdKm5khcfKdylcg==", - "dev": true, - "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.6.1", - "core-js-compat": "^3.36.1" - }, - "peerDependencies": { - "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" - } - }, - "node_modules/babel-plugin-polyfill-regenerator": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.2.tgz", - "integrity": "sha512-2R25rQZWP63nGwaAswvDazbPXfrM3HwVoBXK6HcqeKrSrL/JqcC/rDcf95l4r7LXLyxDXc8uQDa064GubtCABg==", - "dev": true, - "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.6.2" - }, - "peerDependencies": { - "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" - } - }, - "node_modules/babel-preset-current-node-syntax": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz", - "integrity": "sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ==", - "dev": true, - "dependencies": { - "@babel/plugin-syntax-async-generators": "^7.8.4", - "@babel/plugin-syntax-bigint": "^7.8.3", - "@babel/plugin-syntax-class-properties": "^7.8.3", - "@babel/plugin-syntax-import-meta": "^7.8.3", - "@babel/plugin-syntax-json-strings": "^7.8.3", - "@babel/plugin-syntax-logical-assignment-operators": "^7.8.3", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", - "@babel/plugin-syntax-numeric-separator": "^7.8.3", - "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", - "@babel/plugin-syntax-optional-chaining": "^7.8.3", - "@babel/plugin-syntax-top-level-await": "^7.8.3" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/babel-preset-jest": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz", - "integrity": "sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==", - "dev": true, - "dependencies": { - "babel-plugin-jest-hoist": "^29.6.3", - "babel-preset-current-node-syntax": "^1.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true - }, - "node_modules/base64-js": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/bl": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", - "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", - "dev": true, - "dependencies": { - "buffer": "^5.5.0", - "inherits": "^2.0.4", - "readable-stream": "^3.4.0" - } - }, - "node_modules/boolbase": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", - "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", - "dev": true - }, - "node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/braces": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", - "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", - "dev": true, - "license": "MIT", - "dependencies": { - "fill-range": "^7.1.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/browserslist": { - "version": "4.23.0", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.0.tgz", - "integrity": "sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "dependencies": { - "caniuse-lite": "^1.0.30001587", - "electron-to-chromium": "^1.4.668", - "node-releases": "^2.0.14", - "update-browserslist-db": "^1.0.13" - }, - "bin": { - "browserslist": "cli.js" - }, - "engines": { - "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" - } - }, - "node_modules/bser": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", - "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", - "dev": true, - "dependencies": { - "node-int64": "^0.4.0" - } - }, - "node_modules/buffer": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", - "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.1.13" - } - }, - "node_modules/buffer-from": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", - "dev": true - }, - "node_modules/cac": { - "version": "6.7.14", - "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz", - "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/cacheable": { - "version": "1.8.9", - "resolved": "https://registry.npmjs.org/cacheable/-/cacheable-1.8.9.tgz", - "integrity": "sha512-FicwAUyWnrtnd4QqYAoRlNs44/a1jTL7XDKqm5gJ90wz1DQPlC7U2Rd1Tydpv+E7WAr4sQHuw8Q8M3nZMAyecQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "hookified": "^1.7.1", - "keyv": "^5.3.1" - } - }, - "node_modules/cacheable/node_modules/keyv": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-5.3.2.tgz", - "integrity": "sha512-Lji2XRxqqa5Wg+CHLVfFKBImfJZ4pCSccu9eVWK6w4c2SDFLd8JAn1zqTuSFnsxb7ope6rMsnIHfp+eBbRBRZQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@keyv/serialize": "^1.0.3" - } - }, - "node_modules/call-bind": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", - "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", - "dev": true, - "dependencies": { - "es-define-property": "^1.0.0", - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.4", - "set-function-length": "^1.2.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/caniuse-lite": { - "version": "1.0.30001618", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001618.tgz", - "integrity": "sha512-p407+D1tIkDvsEAPS22lJxLQQaG8OTBEqo0KhzfABGk0TU4juBNDSfH0hyAp/HRyx+M8L17z/ltyhxh27FTfQg==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/caniuse-lite" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ] - }, - "node_modules/chai": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/chai/-/chai-5.2.0.tgz", - "integrity": "sha512-mCuXncKXk5iCLhfhwTc0izo0gtEmpz5CtG2y8GiOINBlMVS6v8TMRc5TaLWKS6692m9+dVVfzgeVxR5UxWHTYw==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "assertion-error": "^2.0.1", - "check-error": "^2.1.1", - "deep-eql": "^5.0.1", - "loupe": "^3.1.0", - "pathval": "^2.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/check-error": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/check-error/-/check-error-2.1.1.tgz", - "integrity": "sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">= 16" - } - }, - "node_modules/chrome-trace-event": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz", - "integrity": "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==", - "dev": true, - "peer": true, - "engines": { - "node": ">=6.0" - } - }, - "node_modules/ci-info": { - "version": "3.9.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", - "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/sibiraj-s" - } - ], - "engines": { - "node": ">=8" - } - }, - "node_modules/cli-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", - "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", - "dev": true, - "dependencies": { - "restore-cursor": "^3.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cli-spinners": { - "version": "2.9.2", - "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz", - "integrity": "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==", - "dev": true, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/clone": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", - "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==", - "dev": true, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/clone-deep": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", - "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", - "dev": true, - "dependencies": { - "is-plain-object": "^2.0.4", - "kind-of": "^6.0.2", - "shallow-clone": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true - }, - "node_modules/colord": { - "version": "2.9.3", - "resolved": "https://registry.npmjs.org/colord/-/colord-2.9.3.tgz", - "integrity": "sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw==", - "dev": true, - "license": "MIT" - }, - "node_modules/commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true, - "peer": true - }, - "node_modules/commondir": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", - "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==", - "dev": true - }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true - }, - "node_modules/confusing-browser-globals": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/confusing-browser-globals/-/confusing-browser-globals-1.0.11.tgz", - "integrity": "sha512-JsPKdmh8ZkmnHxDk55FZ1TqVLvEQTvoByJZRN9jzI0UjxK/QgAmsphz7PGtqgPieQZ/CQcHWXCR7ATDNhGe+YA==", - "dev": true - }, - "node_modules/convert-source-map": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", - "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", - "dev": true - }, - "node_modules/core-js": { - "version": "2.6.12", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.12.tgz", - "integrity": "sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==", - "deprecated": "core-js@<3.23.3 is no longer maintained and not recommended for usage due to the number of issues. Because of the V8 engine whims, feature detection in old core-js versions could cause a slowdown up to 100x even if nothing is polyfilled. Some versions have web compatibility issues. Please, upgrade your dependencies to the actual version of core-js.", - "dev": true, - "hasInstallScript": true - }, - "node_modules/core-js-compat": { - "version": "3.37.1", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.37.1.tgz", - "integrity": "sha512-9TNiImhKvQqSUkOvk/mMRZzOANTiEVC7WaBNhHcKM7x+/5E1l5NvsysR19zuDQScE8k+kfQXWRN3AtS/eOSHpg==", - "dev": true, - "dependencies": { - "browserslist": "^4.23.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/core-js" - } - }, - "node_modules/cosmiconfig": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-9.0.0.tgz", - "integrity": "sha512-itvL5h8RETACmOTFc4UfIyB2RfEHi71Ax6E/PivVxq9NseKbOWpeyHEOIbmAw1rs8Ak0VursQNww7lf7YtUwzg==", - "dev": true, - "license": "MIT", - "dependencies": { - "env-paths": "^2.2.1", - "import-fresh": "^3.3.0", - "js-yaml": "^4.1.0", - "parse-json": "^5.2.0" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/d-fischer" - }, - "peerDependencies": { - "typescript": ">=4.9.5" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/cosmiconfig/node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true, - "license": "Python-2.0" - }, - "node_modules/cosmiconfig/node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "license": "MIT", - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/css-functions-list": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/css-functions-list/-/css-functions-list-3.2.3.tgz", - "integrity": "sha512-IQOkD3hbR5KrN93MtcYuad6YPuTSUhntLHDuLEbFWE+ff2/XSZNdZG+LcbbIW5AXKg/WFIfYItIzVoHngHXZzA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12 || >=16" - } - }, - "node_modules/css-tree": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-3.1.0.tgz", - "integrity": "sha512-0eW44TGN5SQXU1mWSkKwFstI/22X2bG1nYzZTYMAWjylYURhse752YgbE4Cx46AC+bAvI+/dYTPRk1LqSUnu6w==", - "dev": true, - "license": "MIT", - "dependencies": { - "mdn-data": "2.12.2", - "source-map-js": "^1.0.1" - }, - "engines": { - "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0" - } - }, - "node_modules/cssesc": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", - "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", - "dev": true, - "bin": { - "cssesc": "bin/cssesc" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/csstype": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", - "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", - "dev": true, - "license": "MIT" - }, - "node_modules/data-view-buffer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.1.tgz", - "integrity": "sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.6", - "es-errors": "^1.3.0", - "is-data-view": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/data-view-byte-length": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.1.tgz", - "integrity": "sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.7", - "es-errors": "^1.3.0", - "is-data-view": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/data-view-byte-offset": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.0.tgz", - "integrity": "sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.6", - "es-errors": "^1.3.0", - "is-data-view": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/debug": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", - "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/deep-eql": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-5.0.2.tgz", - "integrity": "sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/deep-is": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", - "dev": true - }, - "node_modules/defaults": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz", - "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==", - "dev": true, - "dependencies": { - "clone": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/define-data-property": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", - "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", - "dev": true, - "dependencies": { - "es-define-property": "^1.0.0", - "es-errors": "^1.3.0", - "gopd": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/define-properties": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", - "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", - "dev": true, - "dependencies": { - "define-data-property": "^1.0.1", - "has-property-descriptors": "^1.0.0", - "object-keys": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/dequal": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", - "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/dir-glob": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", - "dev": true, - "dependencies": { - "path-type": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", - "dev": true, - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/dom-serializer": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", - "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", - "dev": true, - "dependencies": { - "domelementtype": "^2.3.0", - "domhandler": "^5.0.2", - "entities": "^4.2.0" - }, - "funding": { - "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" - } - }, - "node_modules/domelementtype": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", - "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fb55" - } - ] - }, - "node_modules/domhandler": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", - "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", - "dev": true, - "dependencies": { - "domelementtype": "^2.3.0" - }, - "engines": { - "node": ">= 4" - }, - "funding": { - "url": "https://github.com/fb55/domhandler?sponsor=1" - } - }, - "node_modules/domutils": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.1.0.tgz", - "integrity": "sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==", - "dev": true, - "dependencies": { - "dom-serializer": "^2.0.0", - "domelementtype": "^2.3.0", - "domhandler": "^5.0.3" - }, - "funding": { - "url": "https://github.com/fb55/domutils?sponsor=1" - } - }, - "node_modules/dotenv": { - "version": "16.4.7", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.7.tgz", - "integrity": "sha512-47qPchRCykZC03FhkYAhrvwU4xDBFIj1QPqaarj6mdM/hgUzfPHcpkHJOn3mJAufFeeAxAzeGsr5X0M4k6fLZQ==", - "dev": true, - "license": "BSD-2-Clause", - "peer": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://dotenvx.com" - } - }, - "node_modules/electron-to-chromium": { - "version": "1.4.767", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.767.tgz", - "integrity": "sha512-nzzHfmQqBss7CE3apQHkHjXW77+8w3ubGCIoEijKCJebPufREaFETgGXWTkh32t259F3Kcq+R8MZdFdOJROgYw==", - "dev": true - }, - "node_modules/emoji-regex": { - "version": "10.3.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.3.0.tgz", - "integrity": "sha512-QpLs9D9v9kArv4lfDEgg1X/gN5XLnf/A6l9cs8SPZLRZR3ZkY9+kwIQTxm+fsSej5UMYGE8fdoaZVIBlqG0XTw==", - "dev": true - }, - "node_modules/enhanced-resolve": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-0.9.1.tgz", - "integrity": "sha512-kxpoMgrdtkXZ5h0SeraBS1iRntpTpQ3R8ussdb38+UAFnMGX5DDyJXePm+OCHOcoXvHDw7mc2erbJBpDnl7TPw==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.1.2", - "memory-fs": "^0.2.0", - "tapable": "^0.1.8" - }, - "engines": { - "node": ">=0.6" - } - }, - "node_modules/entities": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", - "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", - "dev": true, - "engines": { - "node": ">=0.12" - }, - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" - } - }, - "node_modules/env-paths": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", - "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-arrayish": "^0.2.1" - } - }, - "node_modules/es-abstract": { - "version": "1.23.3", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.3.tgz", - "integrity": "sha512-e+HfNH61Bj1X9/jLc5v1owaLYuHdeHHSQlkhCBiTK8rBvKaULl/beGMxwrMXjpYrv4pz22BlY570vVePA2ho4A==", - "dev": true, - "dependencies": { - "array-buffer-byte-length": "^1.0.1", - "arraybuffer.prototype.slice": "^1.0.3", - "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.7", - "data-view-buffer": "^1.0.1", - "data-view-byte-length": "^1.0.1", - "data-view-byte-offset": "^1.0.0", - "es-define-property": "^1.0.0", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.0.0", - "es-set-tostringtag": "^2.0.3", - "es-to-primitive": "^1.2.1", - "function.prototype.name": "^1.1.6", - "get-intrinsic": "^1.2.4", - "get-symbol-description": "^1.0.2", - "globalthis": "^1.0.3", - "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.2", - "has-proto": "^1.0.3", - "has-symbols": "^1.0.3", - "hasown": "^2.0.2", - "internal-slot": "^1.0.7", - "is-array-buffer": "^3.0.4", - "is-callable": "^1.2.7", - "is-data-view": "^1.0.1", - "is-negative-zero": "^2.0.3", - "is-regex": "^1.1.4", - "is-shared-array-buffer": "^1.0.3", - "is-string": "^1.0.7", - "is-typed-array": "^1.1.13", - "is-weakref": "^1.0.2", - "object-inspect": "^1.13.1", - "object-keys": "^1.1.1", - "object.assign": "^4.1.5", - "regexp.prototype.flags": "^1.5.2", - "safe-array-concat": "^1.1.2", - "safe-regex-test": "^1.0.3", - "string.prototype.trim": "^1.2.9", - "string.prototype.trimend": "^1.0.8", - "string.prototype.trimstart": "^1.0.8", - "typed-array-buffer": "^1.0.2", - "typed-array-byte-length": "^1.0.1", - "typed-array-byte-offset": "^1.0.2", - "typed-array-length": "^1.0.6", - "unbox-primitive": "^1.0.2", - "which-typed-array": "^1.1.15" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/es-define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", - "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", - "dev": true, - "dependencies": { - "get-intrinsic": "^1.2.4" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-errors": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", - "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", - "dev": true, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-module-lexer": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.6.0.tgz", - "integrity": "sha512-qqnD1yMU6tk/jnaMosogGySTZP8YtUgAffA9nMN+E/rjxcfRQ6IEk7IiozUjgxKoFHBGjTLnrHB/YC45r/59EQ==", - "dev": true, - "license": "MIT", - "peer": true - }, - "node_modules/es-object-atoms": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.0.0.tgz", - "integrity": "sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==", - "dev": true, - "dependencies": { - "es-errors": "^1.3.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-set-tostringtag": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.3.tgz", - "integrity": "sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==", - "dev": true, - "dependencies": { - "get-intrinsic": "^1.2.4", - "has-tostringtag": "^1.0.2", - "hasown": "^2.0.1" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-shim-unscopables": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.2.tgz", - "integrity": "sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==", - "dev": true, - "dependencies": { - "hasown": "^2.0.0" - } - }, - "node_modules/es-to-primitive": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", - "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", - "dev": true, - "dependencies": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/esbuild": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.1.tgz", - "integrity": "sha512-BGO5LtrGC7vxnqucAe/rmvKdJllfGaYWdyABvyMoXQlfYMb2bbRuReWR5tEGE//4LcNJj9XrkovTqNYRFZHAMQ==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "peer": true, - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=18" - }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.25.1", - "@esbuild/android-arm": "0.25.1", - "@esbuild/android-arm64": "0.25.1", - "@esbuild/android-x64": "0.25.1", - "@esbuild/darwin-arm64": "0.25.1", - "@esbuild/darwin-x64": "0.25.1", - "@esbuild/freebsd-arm64": "0.25.1", - "@esbuild/freebsd-x64": "0.25.1", - "@esbuild/linux-arm": "0.25.1", - "@esbuild/linux-arm64": "0.25.1", - "@esbuild/linux-ia32": "0.25.1", - "@esbuild/linux-loong64": "0.25.1", - "@esbuild/linux-mips64el": "0.25.1", - "@esbuild/linux-ppc64": "0.25.1", - "@esbuild/linux-riscv64": "0.25.1", - "@esbuild/linux-s390x": "0.25.1", - "@esbuild/linux-x64": "0.25.1", - "@esbuild/netbsd-arm64": "0.25.1", - "@esbuild/netbsd-x64": "0.25.1", - "@esbuild/openbsd-arm64": "0.25.1", - "@esbuild/openbsd-x64": "0.25.1", - "@esbuild/sunos-x64": "0.25.1", - "@esbuild/win32-arm64": "0.25.1", - "@esbuild/win32-ia32": "0.25.1", - "@esbuild/win32-x64": "0.25.1" - } - }, - "node_modules/escalade": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", - "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/eslint": { - "version": "8.57.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz", - "integrity": "sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==", - "dev": true, - "dependencies": { - "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.6.1", - "@eslint/eslintrc": "^2.1.4", - "@eslint/js": "8.57.0", - "@humanwhocodes/config-array": "^0.11.14", - "@humanwhocodes/module-importer": "^1.0.1", - "@nodelib/fs.walk": "^1.2.8", - "@ungap/structured-clone": "^1.2.0", - "ajv": "^6.12.4", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", - "debug": "^4.3.2", - "doctrine": "^3.0.0", - "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.2.2", - "eslint-visitor-keys": "^3.4.3", - "espree": "^9.6.1", - "esquery": "^1.4.2", - "esutils": "^2.0.2", - "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", - "find-up": "^5.0.0", - "glob-parent": "^6.0.2", - "globals": "^13.19.0", - "graphemer": "^1.4.0", - "ignore": "^5.2.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "is-path-inside": "^3.0.3", - "js-yaml": "^4.1.0", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", - "lodash.merge": "^4.6.2", - "minimatch": "^3.1.2", - "natural-compare": "^1.4.0", - "optionator": "^0.9.3", - "strip-ansi": "^6.0.1", - "text-table": "^0.2.0" - }, - "bin": { - "eslint": "bin/eslint.js" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint-config-airbnb-base": { - "version": "15.0.0", - "resolved": "https://registry.npmjs.org/eslint-config-airbnb-base/-/eslint-config-airbnb-base-15.0.0.tgz", - "integrity": "sha512-xaX3z4ZZIcFLvh2oUNvcX5oEofXda7giYmuplVxoOg5A7EXJMrUyqRgR+mhDhPK8LZ4PttFOBvCYDbX3sUoUig==", - "dev": true, - "dependencies": { - "confusing-browser-globals": "^1.0.10", - "object.assign": "^4.1.2", - "object.entries": "^1.1.5", - "semver": "^6.3.0" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - }, - "peerDependencies": { - "eslint": "^7.32.0 || ^8.2.0", - "eslint-plugin-import": "^2.25.2" - } - }, - "node_modules/eslint-import-resolver-node": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz", - "integrity": "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==", - "dev": true, - "dependencies": { - "debug": "^3.2.7", - "is-core-module": "^2.13.0", - "resolve": "^1.22.4" - } - }, - "node_modules/eslint-import-resolver-node/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/eslint-import-resolver-webpack": { - "version": "0.13.8", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-webpack/-/eslint-import-resolver-webpack-0.13.8.tgz", - "integrity": "sha512-Y7WIaXWV+Q21Rz/PJgUxiW/FTBOWmU8NTLdz+nz9mMoiz5vAev/fOaQxwD7qRzTfE3HSm1qsxZ5uRd7eX+VEtA==", - "dev": true, - "dependencies": { - "array.prototype.find": "^2.2.2", - "debug": "^3.2.7", - "enhanced-resolve": "^0.9.1", - "find-root": "^1.1.0", - "hasown": "^2.0.0", - "interpret": "^1.4.0", - "is-core-module": "^2.13.1", - "is-regex": "^1.1.4", - "lodash": "^4.17.21", - "resolve": "^2.0.0-next.5", - "semver": "^5.7.2" - }, - "engines": { - "node": ">= 6" - }, - "peerDependencies": { - "eslint-plugin-import": ">=1.4.0", - "webpack": ">=1.11.0" - } - }, - "node_modules/eslint-import-resolver-webpack/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/eslint-import-resolver-webpack/node_modules/resolve": { - "version": "2.0.0-next.5", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.5.tgz", - "integrity": "sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==", - "dev": true, - "dependencies": { - "is-core-module": "^2.13.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - }, - "bin": { - "resolve": "bin/resolve" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/eslint-import-resolver-webpack/node_modules/semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "dev": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/eslint-module-utils": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.8.1.tgz", - "integrity": "sha512-rXDXR3h7cs7dy9RNpUlQf80nX31XWJEyGq1tRMo+6GsO5VmTe4UTwtmonAD4ZkAsrfMVDA2wlGJ3790Ys+D49Q==", - "dev": true, - "dependencies": { - "debug": "^3.2.7" - }, - "engines": { - "node": ">=4" - }, - "peerDependenciesMeta": { - "eslint": { - "optional": true - } - } - }, - "node_modules/eslint-module-utils/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/eslint-plugin-file-progress": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-file-progress/-/eslint-plugin-file-progress-1.4.0.tgz", - "integrity": "sha512-MQiq8GGfPc8stuECBktL03CAUu91+kZyufsVjoAEzC7Y4ipAY9M3xB3YYCt7Xv0C5O5t47wlAkqaxnX6LO7DBg==", - "dev": true, - "dependencies": { - "chalk": "^4.1.2", - "ora": "^5.4.1" - }, - "peerDependencies": { - "eslint": "^7.0.0 || ^8.0.0 || ^9.0.0" - } - }, - "node_modules/eslint-plugin-file-progress/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/eslint-plugin-file-progress/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/eslint-plugin-file-progress/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/eslint-plugin-file-progress/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/eslint-plugin-file-progress/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/eslint-plugin-file-progress/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/eslint-plugin-filename-rules": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-filename-rules/-/eslint-plugin-filename-rules-1.3.1.tgz", - "integrity": "sha512-kBMxGFvK3QrRBHMurhFSNa+PFdszezVtBV6egg39TDzlj6D4jL3Xx6oyNjm5xE4C+TdQUBzWwymHJHBPyxOreA==", - "dev": true, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/eslint-plugin-html": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-html/-/eslint-plugin-html-8.1.1.tgz", - "integrity": "sha512-6qmlJsc40D2m3Dn9oEH+0PAOkJhxVu0f5sVItqpCE0YWgYnyP4xCjBc3UWTHaJcY9ARkWOLIIuXLq0ndRnQOHw==", - "dev": true, - "dependencies": { - "htmlparser2": "^9.1.0" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/eslint-plugin-import": { - "version": "2.29.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.29.1.tgz", - "integrity": "sha512-BbPC0cuExzhiMo4Ff1BTVwHpjjv28C5R+btTOGaCRC7UEz801up0JadwkeSk5Ued6TG34uaczuVuH6qyy5YUxw==", - "dev": true, - "peer": true, - "dependencies": { - "array-includes": "^3.1.7", - "array.prototype.findlastindex": "^1.2.3", - "array.prototype.flat": "^1.3.2", - "array.prototype.flatmap": "^1.3.2", - "debug": "^3.2.7", - "doctrine": "^2.1.0", - "eslint-import-resolver-node": "^0.3.9", - "eslint-module-utils": "^2.8.0", - "hasown": "^2.0.0", - "is-core-module": "^2.13.1", - "is-glob": "^4.0.3", - "minimatch": "^3.1.2", - "object.fromentries": "^2.0.7", - "object.groupby": "^1.0.1", - "object.values": "^1.1.7", - "semver": "^6.3.1", - "tsconfig-paths": "^3.15.0" - }, - "engines": { - "node": ">=4" - }, - "peerDependencies": { - "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8" - } - }, - "node_modules/eslint-plugin-import/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "peer": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/eslint-plugin-import/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "peer": true, - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/eslint-plugin-import/node_modules/doctrine": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", - "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", - "dev": true, - "peer": true, - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/eslint-plugin-import/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "peer": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/eslint-plugin-inclusive-language": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-inclusive-language/-/eslint-plugin-inclusive-language-2.2.1.tgz", - "integrity": "sha512-RL6avDWXCS0Dcp9axhvHRUp65qG07qjOrh6J4BNNahPvRY3PuYGnAd0H1strZ9cob79JiEW4Bq0j3gEuzbv0/A==", - "dev": true, - "dependencies": { - "humps": "^2.0.1" - } - }, - "node_modules/eslint-plugin-jest": { - "version": "28.5.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-28.5.0.tgz", - "integrity": "sha512-6np6DGdmNq/eBbA7HOUNV8fkfL86PYwBfwyb8n23FXgJNTR8+ot3smRHjza9LGsBBZRypK3qyF79vMjohIL8eQ==", - "dev": true, - "dependencies": { - "@typescript-eslint/utils": "^6.0.0 || ^7.0.0" - }, - "engines": { - "node": "^16.10.0 || ^18.12.0 || >=20.0.0" - }, - "peerDependencies": { - "@typescript-eslint/eslint-plugin": "^6.0.0 || ^7.0.0", - "eslint": "^7.0.0 || ^8.0.0 || ^9.0.0", - "jest": "*" - }, - "peerDependenciesMeta": { - "@typescript-eslint/eslint-plugin": { - "optional": true - }, - "jest": { - "optional": true - } - } - }, - "node_modules/eslint-plugin-plugin-rules": { - "resolved": "../../../../../../../src/Administration/Resources/app/administration/eslint-rules/plugin-rules", - "link": true - }, - "node_modules/eslint-plugin-simple-import-sort": { - "version": "12.1.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-simple-import-sort/-/eslint-plugin-simple-import-sort-12.1.0.tgz", - "integrity": "sha512-Y2fqAfC11TcG/WP3TrI1Gi3p3nc8XJyEOJYHyEPEGI/UAgNx6akxxlX74p7SbAQdLcgASKhj8M0GKvH3vq/+ig==", - "dev": true, - "peerDependencies": { - "eslint": ">=5.0.0" - } - }, - "node_modules/eslint-plugin-sw-core-rules": { - "resolved": "../../../../../../../src/Administration/Resources/app/administration/eslint-rules/core-rules", - "link": true - }, - "node_modules/eslint-plugin-sw-deprecation-rules": { - "resolved": "../../../../../../../src/Administration/Resources/app/administration/eslint-rules/deprecation-rules", - "link": true - }, - "node_modules/eslint-plugin-sw-test-rules": { - "resolved": "../../../../../../../src/Administration/Resources/app/administration/eslint-rules/test-rules", - "link": true - }, - "node_modules/eslint-plugin-twig-vue": { - "resolved": "../../../../../../../src/Administration/Resources/app/administration/twigVuePlugin", - "link": true - }, - "node_modules/eslint-plugin-vue": { - "version": "9.26.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-9.26.0.tgz", - "integrity": "sha512-eTvlxXgd4ijE1cdur850G6KalZqk65k1JKoOI2d1kT3hr8sPD07j1q98FRFdNnpxBELGPWxZmInxeHGF/GxtqQ==", - "dev": true, - "dependencies": { - "@eslint-community/eslint-utils": "^4.4.0", - "globals": "^13.24.0", - "natural-compare": "^1.4.0", - "nth-check": "^2.1.1", - "postcss-selector-parser": "^6.0.15", - "semver": "^7.6.0", - "vue-eslint-parser": "^9.4.2", - "xml-name-validator": "^4.0.0" - }, - "engines": { - "node": "^14.17.0 || >=16.0.0" - }, - "peerDependencies": { - "eslint": "^6.2.0 || ^7.0.0 || ^8.0.0 || ^9.0.0" - } - }, - "node_modules/eslint-plugin-vue/node_modules/globals": { - "version": "13.24.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", - "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", - "dev": true, - "dependencies": { - "type-fest": "^0.20.2" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint-plugin-vue/node_modules/semver": { - "version": "7.6.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", - "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/eslint-plugin-vuejs-accessibility": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-vuejs-accessibility/-/eslint-plugin-vuejs-accessibility-2.3.0.tgz", - "integrity": "sha512-zQ6IzK+3obZzPsjeVUeL3xAUlMHXZgRZ8vgXvQAmoZVbsp1xZe6UwXIKUFIim5h3tq/7bOLgei09GoBjJQs+Cw==", - "dev": true, - "dependencies": { - "aria-query": "^5.3.0", - "emoji-regex": "^10.0.0", - "vue-eslint-parser": "^9.0.1" - }, - "engines": { - "node": ">=16.0.0" - }, - "peerDependencies": { - "eslint": "^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 || ^9.0.0" - } - }, - "node_modules/eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", - "dev": true, - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/eslint-visitor-keys": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", - "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/eslint/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/eslint/node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true - }, - "node_modules/eslint/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/eslint/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/eslint/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/eslint/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/eslint/node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint/node_modules/eslint-scope": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", - "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", - "dev": true, - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint/node_modules/eslint-visitor-keys": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", - "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", - "dev": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint/node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/eslint/node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, - "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint/node_modules/globals": { - "version": "13.24.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", - "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", - "dev": true, - "dependencies": { - "type-fest": "^0.20.2" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/eslint/node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/eslint/node_modules/locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, - "dependencies": { - "p-locate": "^5.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/eslint/node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "dependencies": { - "yocto-queue": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint/node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, - "dependencies": { - "p-limit": "^3.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/espree": { - "version": "9.6.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", - "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", - "dev": true, - "dependencies": { - "acorn": "^8.9.0", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.4.1" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/espree/node_modules/eslint-visitor-keys": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", - "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", - "dev": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "dev": true, - "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/esquery": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", - "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", - "dev": true, - "dependencies": { - "estraverse": "^5.1.0" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/esquery/node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "dev": true, - "dependencies": { - "estraverse": "^5.2.0" - }, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/esrecurse/node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/estree-walker": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", - "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@types/estree": "^1.0.0" - } - }, - "node_modules/esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/events": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", - "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", - "dev": true, - "peer": true, - "engines": { - "node": ">=0.8.x" - } - }, - "node_modules/expect-type": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.2.0.tgz", - "integrity": "sha512-80F22aiJ3GLyVnS/B3HzgR6RelZVumzj9jkL0Rhz4h0xYbNW9PjlQz5h3J/SShErbXBc295vseR4/MIbVmUbeA==", - "dev": true, - "license": "Apache-2.0", - "peer": true, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true - }, - "node_modules/fast-glob": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", - "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.8" - }, - "engines": { - "node": ">=8.6.0" - } - }, - "node_modules/fast-glob/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true - }, - "node_modules/fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", - "dev": true - }, - "node_modules/fast-uri": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.6.tgz", - "integrity": "sha512-Atfo14OibSv5wAp4VWNsFYE1AchQRTv9cBGWET4pZWHzYshFSS9NQI6I57rdKn9croWVMbYFbLhJ+yJvmZIIHw==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fastify" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/fastify" - } - ], - "license": "BSD-3-Clause" - }, - "node_modules/fastest-levenshtein": { - "version": "1.0.16", - "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz", - "integrity": "sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 4.9.1" - } - }, - "node_modules/fastq": { - "version": "1.17.1", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", - "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", - "dev": true, - "dependencies": { - "reusify": "^1.0.4" - } - }, - "node_modules/fb-watchman": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", - "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==", - "dev": true, - "dependencies": { - "bser": "2.1.1" - } - }, - "node_modules/file-entry-cache": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", - "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", - "dev": true, - "dependencies": { - "flat-cache": "^3.0.4" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, - "node_modules/fill-range": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", - "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", - "dev": true, - "license": "MIT", - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/find-babel-config": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/find-babel-config/-/find-babel-config-2.1.1.tgz", - "integrity": "sha512-5Ji+EAysHGe1OipH7GN4qDjok5Z1uw5KAwDCbicU/4wyTZY7CqOCzcWbG7J5ad9mazq67k89fXlbc1MuIfl9uA==", - "dev": true, - "dependencies": { - "json5": "^2.2.3", - "path-exists": "^4.0.0" - } - }, - "node_modules/find-cache-dir": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", - "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==", - "dev": true, - "dependencies": { - "commondir": "^1.0.1", - "make-dir": "^2.0.0", - "pkg-dir": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/find-root": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz", - "integrity": "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==", - "dev": true - }, - "node_modules/find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, - "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/flat-cache": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", - "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", - "dev": true, - "dependencies": { - "flatted": "^3.2.9", - "keyv": "^4.5.3", - "rimraf": "^3.0.2" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, - "node_modules/flatted": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz", - "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==", - "dev": true, - "license": "ISC" - }, - "node_modules/for-each": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", - "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", - "dev": true, - "dependencies": { - "is-callable": "^1.1.3" - } - }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", - "dev": true - }, - "node_modules/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "dev": true, - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/function-bind": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", - "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/function.prototype.name": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.6.tgz", - "integrity": "sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "functions-have-names": "^1.2.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/functions-have-names": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", - "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/gensync": { - "version": "1.0.0-beta.2", - "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", - "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/get-east-asian-width": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.3.0.tgz", - "integrity": "sha512-vpeMIQKxczTD/0s2CdEWHcb0eeJe6TFjxb+J5xgX7hScxqrGuyjmv4c1D4A/gelKfyox0gJJwIHF+fLjeaM8kQ==", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/get-intrinsic": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", - "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", - "dev": true, - "dependencies": { - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "has-proto": "^1.0.1", - "has-symbols": "^1.0.3", - "hasown": "^2.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/get-package-type": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", - "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", - "dev": true, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/get-symbol-description": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.2.tgz", - "integrity": "sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.5", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.4" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/glob": { - "version": "9.3.5", - "resolved": "https://registry.npmjs.org/glob/-/glob-9.3.5.tgz", - "integrity": "sha512-e1LleDykUz2Iu+MTYdkSsuWX8lvAjAcs0Xef0lNIu0S2wOAzuTxCJtcd9S3cijlwYF18EsU3rzb8jPVobxDh9Q==", - "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "minimatch": "^8.0.2", - "minipass": "^4.2.4", - "path-scurry": "^1.6.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.3" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/glob-to-regexp": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", - "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", - "dev": true, - "peer": true - }, - "node_modules/glob/node_modules/minimatch": { - "version": "8.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-8.0.4.tgz", - "integrity": "sha512-W0Wvr9HyFXZRGIDgCicunpQ299OKXs9RgZfaukz4qAW/pJhcpUfupc9c+OObPOFueNy8VSrZgEmDtk6Kh4WzDA==", - "dev": true, - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/global-modules": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-2.0.0.tgz", - "integrity": "sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A==", - "dev": true, - "license": "MIT", - "dependencies": { - "global-prefix": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/global-prefix": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-3.0.0.tgz", - "integrity": "sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==", - "dev": true, - "license": "MIT", - "dependencies": { - "ini": "^1.3.5", - "kind-of": "^6.0.2", - "which": "^1.3.1" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/global-prefix/node_modules/which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dev": true, - "license": "ISC", - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "which": "bin/which" - } - }, - "node_modules/globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/globalthis": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", - "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", - "dev": true, - "dependencies": { - "define-properties": "^1.2.1", - "gopd": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/globby": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", - "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", - "dev": true, - "dependencies": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.9", - "ignore": "^5.2.0", - "merge2": "^1.4.1", - "slash": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/globjoin": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/globjoin/-/globjoin-0.1.4.tgz", - "integrity": "sha512-xYfnw62CKG8nLkZBfWbhWwDw02CHty86jfPcc2cr3ZfeuK9ysoVPPEUxf21bAD/rWAgk52SuBrLJlefNy8mvFg==", - "dev": true, - "license": "MIT" - }, - "node_modules/gopd": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", - "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", - "dev": true, - "dependencies": { - "get-intrinsic": "^1.1.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/graceful-fs": { - "version": "4.2.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "dev": true - }, - "node_modules/graphemer": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", - "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", - "dev": true - }, - "node_modules/has": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.4.tgz", - "integrity": "sha512-qdSAmqLF6209RFj4VVItywPMbm3vWylknmB3nvNiUIs72xAimcM8nVYxYr7ncvZq5qzk9MKIZR8ijqD/1QuYjQ==", - "dev": true, - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/has-bigints": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", - "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/has-property-descriptors": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", - "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", - "dev": true, - "dependencies": { - "es-define-property": "^1.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-proto": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", - "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-symbols": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", - "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-tostringtag": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", - "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", - "dev": true, - "dependencies": { - "has-symbols": "^1.0.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/hasown": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", - "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", - "dev": true, - "dependencies": { - "function-bind": "^1.1.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/hookified": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/hookified/-/hookified-1.8.1.tgz", - "integrity": "sha512-GrO2l93P8xCWBSTBX9l2BxI78VU/MAAYag+pG8curS3aBGy0++ZlxrQ7PdUOUVMbn5BwkGb6+eRrnf43ipnFEA==", - "dev": true, - "license": "MIT" - }, - "node_modules/html-tags": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/html-tags/-/html-tags-3.3.1.tgz", - "integrity": "sha512-ztqyC3kLto0e9WbNp0aeP+M3kTt+nbaIveGmUxAtZa+8iFgKLUOD4YKM5j+f3QD89bra7UeumolZHKuOXnTmeQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/htmlparser2": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-9.1.0.tgz", - "integrity": "sha512-5zfg6mHUoaer/97TxnGpxmbR7zJtPwIYFMZ/H5ucTlPZhKvtum05yiPK3Mgai3a0DyVxv7qYqoweaEd2nrYQzQ==", - "dev": true, - "funding": [ - "https://github.com/fb55/htmlparser2?sponsor=1", - { - "type": "github", - "url": "https://github.com/sponsors/fb55" - } - ], - "dependencies": { - "domelementtype": "^2.3.0", - "domhandler": "^5.0.3", - "domutils": "^3.1.0", - "entities": "^4.5.0" - } - }, - "node_modules/humps": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/humps/-/humps-2.0.1.tgz", - "integrity": "sha512-E0eIbrFWUhwfXJmsbdjRQFQPrl5pTEoKlz163j1mTqqUnU9PgR4AgB8AIITzuB3vLBdxZXyZ9TDIrwB2OASz4g==", - "dev": true - }, - "node_modules/ieee754": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/ignore": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", - "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==", - "dev": true, - "engines": { - "node": ">= 4" - } - }, - "node_modules/import-fresh": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", - "dev": true, - "dependencies": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/import-fresh/node_modules/resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", - "dev": true, - "engines": { - "node": ">=0.8.19" - } - }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "dev": true, - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true - }, - "node_modules/ini": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", - "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", - "dev": true, - "license": "ISC" - }, - "node_modules/internal-slot": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.7.tgz", - "integrity": "sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==", - "dev": true, - "dependencies": { - "es-errors": "^1.3.0", - "hasown": "^2.0.0", - "side-channel": "^1.0.4" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/interpret": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz", - "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==", - "dev": true, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/is-array-buffer": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.4.tgz", - "integrity": "sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.2.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", - "dev": true, - "license": "MIT" - }, - "node_modules/is-bigint": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", - "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", - "dev": true, - "dependencies": { - "has-bigints": "^1.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-boolean-object": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", - "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-callable": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", - "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-core-module": { - "version": "2.13.1", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz", - "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==", - "dev": true, - "dependencies": { - "hasown": "^2.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-data-view": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.1.tgz", - "integrity": "sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w==", - "dev": true, - "dependencies": { - "is-typed-array": "^1.1.13" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-date-object": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", - "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", - "dev": true, - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-interactive": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", - "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-negative-zero": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", - "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/is-number-object": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", - "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", - "dev": true, - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-path-inside": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", - "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, - "dependencies": { - "isobject": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-regex": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", - "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-shared-array-buffer": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.3.tgz", - "integrity": "sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.7" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-string": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", - "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", - "dev": true, - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-symbol": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", - "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", - "dev": true, - "dependencies": { - "has-symbols": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-typed-array": { - "version": "1.1.13", - "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.13.tgz", - "integrity": "sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==", - "dev": true, - "dependencies": { - "which-typed-array": "^1.1.14" - }, - "engines": { - "node": ">= 0.4" + "has-symbols": "^1.0.3" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-unicode-supported": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", - "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", - "dev": true, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-weakref": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", - "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2" + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/isarray": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", - "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", - "dev": true - }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true - }, - "node_modules/isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/istanbul-lib-coverage": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", - "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/istanbul-lib-instrument": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", - "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", - "dev": true, - "dependencies": { - "@babel/core": "^7.12.3", - "@babel/parser": "^7.14.7", - "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-coverage": "^3.2.0", - "semver": "^6.3.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-haste-map": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.7.0.tgz", - "integrity": "sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==", + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", "dev": true, + "license": "MIT", "dependencies": { - "@jest/types": "^29.6.3", - "@types/graceful-fs": "^4.1.3", - "@types/node": "*", - "anymatch": "^3.0.3", - "fb-watchman": "^2.0.0", - "graceful-fs": "^4.2.9", - "jest-regex-util": "^29.6.3", - "jest-util": "^29.7.0", - "jest-worker": "^29.7.0", - "micromatch": "^4.0.4", - "walker": "^1.0.8" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "function-bind": "^1.1.2" }, - "optionalDependencies": { - "fsevents": "^2.3.2" - } - }, - "node_modules/jest-regex-util": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz", - "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==", - "dev": true, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">= 0.4" } }, - "node_modules/jest-util": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", - "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", + "node_modules/hosted-git-info": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz", + "integrity": "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==", "dev": true, + "license": "ISC", "dependencies": { - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "graceful-fs": "^4.2.9", - "picomatch": "^2.2.3" + "lru-cache": "^6.0.0" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=10" } }, - "node_modules/jest-util/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "node_modules/html-tags": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/html-tags/-/html-tags-3.3.1.tgz", + "integrity": "sha512-ztqyC3kLto0e9WbNp0aeP+M3kTt+nbaIveGmUxAtZa+8iFgKLUOD4YKM5j+f3QD89bra7UeumolZHKuOXnTmeQ==", "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, + "license": "MIT", "engines": { "node": ">=8" }, "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/jest-util/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "node_modules/htmlparser2": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-8.0.2.tgz", + "integrity": "sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA==", "dev": true, + "funding": [ + "https://github.com/fb55/htmlparser2?sponsor=1", + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "license": "MIT", "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3", + "domutils": "^3.0.1", + "entities": "^4.4.0" } }, - "node_modules/jest-util/node_modules/color-convert": { + "node_modules/humps": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "resolved": "https://registry.npmjs.org/humps/-/humps-2.0.1.tgz", + "integrity": "sha512-E0eIbrFWUhwfXJmsbdjRQFQPrl5pTEoKlz163j1mTqqUnU9PgR4AgB8AIITzuB3vLBdxZXyZ9TDIrwB2OASz4g==", "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/jest-util/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true + "license": "MIT" }, - "node_modules/jest-util/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", "dev": true, + "license": "MIT", "engines": { - "node": ">=8" + "node": ">= 4" } }, - "node_modules/jest-util/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "node_modules/import-fresh": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", + "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", "dev": true, + "license": "MIT", "dependencies": { - "has-flag": "^4.0.0" + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" }, "engines": { - "node": ">=8" - } - }, - "node_modules/jest-worker": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", - "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", - "dev": true, - "dependencies": { - "@types/node": "*", - "jest-util": "^29.7.0", - "merge-stream": "^2.0.0", - "supports-color": "^8.0.0" + "node": ">=6" }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/jest-worker/node_modules/has-flag": { + "node_modules/import-lazy": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-4.0.0.tgz", + "integrity": "sha512-rKtvo6a868b5Hu3heneU+L4yEQ4jYKLtjpnPeUdK7h0yzXGmyBTypknlkCvHFBqfX9YlorEiMM6Dnq/5atfHkw==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, - "node_modules/jest-worker/node_modules/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, + "license": "MIT", "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" + "node": ">=0.8.19" } }, - "node_modules/js-tokens": { + "node_modules/indent-string": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true - }, - "node_modules/js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", - "dev": true, - "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/jsesc": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", - "dev": true, - "bin": { - "jsesc": "bin/jsesc" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/json-buffer": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", - "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", - "dev": true - }, - "node_modules/json-parse-even-better-errors": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", - "dev": true - }, - "node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, - "node_modules/json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", - "dev": true - }, - "node_modules/json5": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", - "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", - "dev": true, - "bin": { - "json5": "lib/cli.js" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/keyv": { - "version": "4.5.4", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", - "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", - "dev": true, - "dependencies": { - "json-buffer": "3.0.1" - } - }, - "node_modules/kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", "dev": true, + "license": "MIT", "engines": { - "node": ">=0.10.0" + "node": ">=8" } }, - "node_modules/known-css-properties": { - "version": "0.35.0", - "resolved": "https://registry.npmjs.org/known-css-properties/-/known-css-properties-0.35.0.tgz", - "integrity": "sha512-a/RAk2BfKk+WFGhhOCAYqSiFLc34k8Mt/6NWRI4joER0EYUzXIcFivjjnoD3+XU1DggLn/tZc3DOAgke7l8a4A==", - "dev": true, - "license": "MIT" - }, - "node_modules/levn": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", "dev": true, + "license": "ISC", "dependencies": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" - }, - "engines": { - "node": ">= 0.8.0" + "once": "^1.3.0", + "wrappy": "1" } }, - "node_modules/lines-and-columns": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", - "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", "dev": true, - "license": "MIT" + "license": "ISC" }, - "node_modules/loader-runner": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz", - "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==", + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", "dev": true, - "peer": true, - "engines": { - "node": ">=6.11.5" - } + "license": "ISC" }, - "node_modules/locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "node_modules/internal-slot": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.1.0.tgz", + "integrity": "sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==", "dev": true, + "license": "MIT", "dependencies": { - "p-locate": "^4.1.0" + "es-errors": "^1.3.0", + "hasown": "^2.0.2", + "side-channel": "^1.1.0" }, "engines": { - "node": ">=8" + "node": ">= 0.4" } }, - "node_modules/lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", - "dev": true - }, - "node_modules/lodash.debounce": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", - "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==", - "dev": true - }, - "node_modules/lodash.merge": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", - "dev": true - }, - "node_modules/lodash.truncate": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz", - "integrity": "sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==", - "dev": true, - "license": "MIT" - }, - "node_modules/log-symbols": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", - "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", + "node_modules/is-array-buffer": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.5.tgz", + "integrity": "sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==", "dev": true, + "license": "MIT", "dependencies": { - "chalk": "^4.1.0", - "is-unicode-supported": "^0.1.0" + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "get-intrinsic": "^1.2.6" }, "engines": { - "node": ">=10" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/log-symbols/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "dev": true, + "license": "MIT" + }, + "node_modules/is-async-function": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.1.1.tgz", + "integrity": "sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==", "dev": true, + "license": "MIT", "dependencies": { - "color-convert": "^2.0.1" + "async-function": "^1.0.0", + "call-bound": "^1.0.3", + "get-proto": "^1.0.1", + "has-tostringtag": "^1.0.2", + "safe-regex-test": "^1.1.0" }, "engines": { - "node": ">=8" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/log-symbols/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "node_modules/is-bigint": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.1.0.tgz", + "integrity": "sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==", "dev": true, + "license": "MIT", "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" + "has-bigints": "^1.0.2" }, "engines": { - "node": ">=10" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/log-symbols/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "node_modules/is-boolean-object": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.2.2.tgz", + "integrity": "sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==", "dev": true, + "license": "MIT", "dependencies": { - "color-name": "~1.1.4" + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" }, "engines": { - "node": ">=7.0.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/log-symbols/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/log-symbols/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "node_modules/is-callable": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", "dev": true, + "license": "MIT", "engines": { - "node": ">=8" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/log-symbols/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "node_modules/is-core-module": { + "version": "2.16.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", + "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", "dev": true, + "license": "MIT", "dependencies": { - "has-flag": "^4.0.0" + "hasown": "^2.0.2" }, "engines": { - "node": ">=8" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/loupe": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/loupe/-/loupe-3.1.3.tgz", - "integrity": "sha512-kkIp7XSkP78ZxJEsSxW3712C6teJVoeHHwgo9zJ380de7IYyJ2ISlxojcH2pC5OFLewESmnRi/+XCDIEEVyoug==", + "node_modules/is-data-view": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.2.tgz", + "integrity": "sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==", "dev": true, "license": "MIT", - "peer": true - }, - "node_modules/lru-cache": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", - "dev": true, "dependencies": { - "yallist": "^3.0.2" + "call-bound": "^1.0.2", + "get-intrinsic": "^1.2.6", + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/magic-string": { - "version": "0.30.17", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.17.tgz", - "integrity": "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==", + "node_modules/is-date-object": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.1.0.tgz", + "integrity": "sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==", "dev": true, "license": "MIT", - "peer": true, - "dependencies": { - "@jridgewell/sourcemap-codec": "^1.5.0" - } - }, - "node_modules/make-dir": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", - "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", - "dev": true, "dependencies": { - "pify": "^4.0.1", - "semver": "^5.6.0" + "call-bound": "^1.0.2", + "has-tostringtag": "^1.0.2" }, "engines": { - "node": ">=6" - } - }, - "node_modules/make-dir/node_modules/semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "dev": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/makeerror": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", - "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", - "dev": true, - "dependencies": { - "tmpl": "1.0.5" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/mathml-tag-names": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/mathml-tag-names/-/mathml-tag-names-2.1.3.tgz", - "integrity": "sha512-APMBEanjybaPzUrfqU0IMU5I0AswKMH7k8OTLs0vvV4KZpExkTkY87nR/zpbuTPj+gARop7aGUbl11pnDfW6xg==", + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", "dev": true, "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "engines": { + "node": ">=0.10.0" } }, - "node_modules/mdn-data": { - "version": "2.12.2", - "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.12.2.tgz", - "integrity": "sha512-IEn+pegP1aManZuckezWCO+XZQDplx1366JoVhTpMpBB1sPey/SbveZQUosKiKiGYjg1wH4pMlNgXbCiYgihQA==", - "dev": true, - "license": "CC0-1.0" - }, - "node_modules/memory-fs": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.2.0.tgz", - "integrity": "sha512-+y4mDxU4rvXXu5UDSGCGNiesFmwCHuefGMoPCO1WYucNYj7DsLqrFaa2fXVI0H+NNiPTwwzKwspn9yTZqUGqng==", - "dev": true - }, - "node_modules/meow": { - "version": "13.2.0", - "resolved": "https://registry.npmjs.org/meow/-/meow-13.2.0.tgz", - "integrity": "sha512-pxQJQzB6djGPXh08dacEloMFopsOqGVRKFPYvPOt9XDZ1HasbgDZA74CJGreSU4G3Ak7EFJGoiH2auq+yXISgA==", + "node_modules/is-finalizationregistry": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.1.1.tgz", + "integrity": "sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==", "dev": true, "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3" + }, "engines": { - "node": ">=18" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/merge-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "dev": true - }, - "node_modules/merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", "dev": true, + "license": "MIT", "engines": { - "node": ">= 8" + "node": ">=8" } }, - "node_modules/micromatch": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", - "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "node_modules/is-generator-function": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.2.tgz", + "integrity": "sha512-upqt1SkGkODW9tsGNG5mtXTXtECizwtS2kA161M+gJPc1xdb/Ax629af6YrTwcOeQHbewrPNlE5Dx7kzvXTizA==", "dev": true, "license": "MIT", "dependencies": { - "braces": "^3.0.3", - "picomatch": "^2.3.1" + "call-bound": "^1.0.4", + "generator-function": "^2.0.0", + "get-proto": "^1.0.1", + "has-tostringtag": "^1.0.2", + "safe-regex-test": "^1.1.0" }, "engines": { - "node": ">=8.6" - } - }, - "node_modules/mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "dev": true, - "peer": true, - "engines": { - "node": ">= 0.6" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", "dev": true, - "peer": true, + "license": "MIT", "dependencies": { - "mime-db": "1.52.0" + "is-extglob": "^2.1.1" }, "engines": { - "node": ">= 0.6" + "node": ">=0.10.0" } }, - "node_modules/mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "node_modules/is-map": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz", + "integrity": "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==", "dev": true, + "license": "MIT", "engines": { - "node": ">=6" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/mimic-function": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/mimic-function/-/mimic-function-5.0.1.tgz", - "integrity": "sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==", + "node_modules/is-negative-zero": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", + "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", "dev": true, "license": "MIT", - "peer": true, "engines": { - "node": ">=18" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/minimatch": { - "version": "9.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.4.tgz", - "integrity": "sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==", + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-number-object": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.1.1.tgz", + "integrity": "sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==", "dev": true, + "license": "MIT", "dependencies": { - "brace-expansion": "^2.0.1" + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" }, "engines": { - "node": ">=16 || 14 >=14.17" + "node": ">= 0.4" }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/minimist": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", - "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", - "dev": true, "funding": { "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/minipass": { - "version": "4.2.8", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-4.2.8.tgz", - "integrity": "sha512-fNzuVyifolSLFL4NzpF+wEF4qrgqaaKX0haXPQEdQ7NKAN+WecoKMHV09YcuL/DHxrUsYQOK3MiuDf7Ip2OXfQ==", + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, - "node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true, - "license": "MIT" - }, - "node_modules/nanoid": { - "version": "3.3.11", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", - "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", + "node_modules/is-plain-obj": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", + "integrity": "sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==", "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], "license": "MIT", - "bin": { - "nanoid": "bin/nanoid.cjs" - }, "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + "node": ">=0.10.0" } }, - "node_modules/natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", - "dev": true - }, - "node_modules/neo-async": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", - "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", - "dev": true, - "peer": true - }, - "node_modules/node-int64": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", - "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==", - "dev": true - }, - "node_modules/node-releases": { - "version": "2.0.14", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", - "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==", - "dev": true - }, - "node_modules/normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "node_modules/is-plain-object": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", + "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } }, - "node_modules/nth-check": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", - "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", + "node_modules/is-regex": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz", + "integrity": "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==", "dev": true, + "license": "MIT", "dependencies": { - "boolbase": "^1.0.0" + "call-bound": "^1.0.2", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" }, - "funding": { - "url": "https://github.com/fb55/nth-check?sponsor=1" - } - }, - "node_modules/object-inspect": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", - "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==", - "dev": true, "funding": { "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "node_modules/is-set": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz", + "integrity": "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/object.assign": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.5.tgz", - "integrity": "sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==", + "node_modules/is-shared-array-buffer": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.4.tgz", + "integrity": "sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.5", - "define-properties": "^1.2.1", - "has-symbols": "^1.0.3", - "object-keys": "^1.1.1" + "call-bound": "^1.0.3" }, "engines": { "node": ">= 0.4" @@ -8608,31 +3256,33 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/object.entries": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.8.tgz", - "integrity": "sha512-cmopxi8VwRIAw/fkijJohSfpef5PdN0pMQJN6VC/ZKvn0LIknWD8KtgY6KlQdEc4tIjcQ3HxSMmnvtzIscdaYQ==", + "node_modules/is-string": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.1.1.tgz", + "integrity": "sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-object-atoms": "^1.0.0" + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" }, "engines": { "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/object.fromentries": { - "version": "2.0.8", - "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.8.tgz", - "integrity": "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==", + "node_modules/is-symbol": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.1.1.tgz", + "integrity": "sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==", "dev": true, - "peer": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.2", - "es-object-atoms": "^1.0.0" + "call-bound": "^1.0.2", + "has-symbols": "^1.1.0", + "safe-regex-test": "^1.1.0" }, "engines": { "node": ">= 0.4" @@ -8641,31 +3291,28 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/object.groupby": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.3.tgz", - "integrity": "sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==", + "node_modules/is-typed-array": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz", + "integrity": "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==", "dev": true, - "peer": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.2" + "which-typed-array": "^1.1.16" }, "engines": { "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/object.values": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.0.tgz", - "integrity": "sha512-yBYjY9QX2hnRmZHAjG/f13MzmBzxzYgQhFrke06TTyKY5zSTEqkOeukBzIdVA3j3ulu8Qa3MbVFShV7T2RmGtQ==", + "node_modules/is-weakmap": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz", + "integrity": "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==", "dev": true, - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-object-atoms": "^1.0.0" - }, + "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -8673,652 +3320,604 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dev": true, - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "node_modules/is-weakref": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.1.1.tgz", + "integrity": "sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew==", "dev": true, + "license": "MIT", "dependencies": { - "mimic-fn": "^2.1.0" + "call-bound": "^1.0.3" }, "engines": { - "node": ">=6" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/optionator": { - "version": "0.9.4", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", - "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", - "dev": true, - "dependencies": { - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0", - "word-wrap": "^1.2.5" - }, - "engines": { - "node": ">= 0.8.0" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/ora": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", - "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==", + "node_modules/is-weakset": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.4.tgz", + "integrity": "sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==", "dev": true, + "license": "MIT", "dependencies": { - "bl": "^4.1.0", - "chalk": "^4.1.0", - "cli-cursor": "^3.1.0", - "cli-spinners": "^2.5.0", - "is-interactive": "^1.0.0", - "is-unicode-supported": "^0.1.0", - "log-symbols": "^4.1.0", - "strip-ansi": "^6.0.0", - "wcwidth": "^1.0.1" + "call-bound": "^1.0.3", + "get-intrinsic": "^1.2.6" }, "engines": { - "node": ">=10" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/ora/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true, + "license": "MIT" + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true, + "license": "ISC" + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/js-yaml": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", + "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", "dev": true, + "license": "MIT", "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" + "argparse": "^2.0.1" }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "bin": { + "js-yaml": "bin/js-yaml.js" } }, - "node_modules/ora/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/json5": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", + "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", "dev": true, + "license": "MIT", "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" + "minimist": "^1.2.0" }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "bin": { + "json5": "lib/cli.js" } }, - "node_modules/ora/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", "dev": true, + "license": "MIT", "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" + "json-buffer": "3.0.1" } }, - "node_modules/ora/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/ora/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", "dev": true, + "license": "MIT", "engines": { - "node": ">=8" + "node": ">=0.10.0" } }, - "node_modules/ora/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "node_modules/known-css-properties": { + "version": "0.26.0", + "resolved": "https://registry.npmjs.org/known-css-properties/-/known-css-properties-0.26.0.tgz", + "integrity": "sha512-5FZRzrZzNTBruuurWpvZnvP9pum+fe0HcK8z/ooo+U+Hmp4vtbyp1/QDsqmufirXy4egGzbaH/y2uCZf+6W5Kg==", + "dev": true, + "license": "MIT" + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", "dev": true, + "license": "MIT", "dependencies": { - "has-flag": "^4.0.0" + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" }, "engines": { - "node": ">=8" + "node": ">= 0.8.0" } }, - "node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "dev": true, + "license": "MIT" + }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", "dev": true, + "license": "MIT", "dependencies": { - "p-try": "^2.0.0" + "p-locate": "^5.0.0" }, "engines": { - "node": ">=6" + "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", "dev": true, - "dependencies": { - "p-limit": "^2.2.0" - }, - "engines": { - "node": ">=8" - } + "license": "MIT" }, - "node_modules/p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", "dev": true, - "engines": { - "node": ">=6" - } + "license": "MIT" }, - "node_modules/parent-module": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "node_modules/lodash.truncate": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz", + "integrity": "sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==", + "dev": true, + "license": "MIT" + }, + "node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", "dev": true, + "license": "ISC", "dependencies": { - "callsites": "^3.0.0" + "yallist": "^4.0.0" }, "engines": { - "node": ">=6" + "node": ">=10" } }, - "node_modules/parse-json": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", - "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "node_modules/magic-string": { + "version": "0.30.21", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", + "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.0.0", - "error-ex": "^1.3.1", - "json-parse-even-better-errors": "^2.3.0", - "lines-and-columns": "^1.1.6" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "@jridgewell/sourcemap-codec": "^1.5.5" } }, - "node_modules/path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "node_modules/map-obj": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-4.3.0.tgz", + "integrity": "sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", "dev": true, + "license": "MIT", "engines": { - "node": ">=0.10.0" + "node": ">= 0.4" } }, - "node_modules/path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "node_modules/mathml-tag-names": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/mathml-tag-names/-/mathml-tag-names-2.1.3.tgz", + "integrity": "sha512-APMBEanjybaPzUrfqU0IMU5I0AswKMH7k8OTLs0vvV4KZpExkTkY87nR/zpbuTPj+gARop7aGUbl11pnDfW6xg==", "dev": true, - "engines": { - "node": ">=8" + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true - }, - "node_modules/path-scurry": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", - "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", + "node_modules/meow": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/meow/-/meow-9.0.0.tgz", + "integrity": "sha512-+obSblOQmRhcyBt62furQqRAQpNyWXo8BuQ5bN7dG8wmwQ+vwHKp/rCFD4CrTP8CsDQD1sjoZ94K417XEUk8IQ==", "dev": true, + "license": "MIT", "dependencies": { - "lru-cache": "^10.2.0", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + "@types/minimist": "^1.2.0", + "camelcase-keys": "^6.2.2", + "decamelize": "^1.2.0", + "decamelize-keys": "^1.1.0", + "hard-rejection": "^2.1.0", + "minimist-options": "4.1.0", + "normalize-package-data": "^3.0.0", + "read-pkg-up": "^7.0.1", + "redent": "^3.0.0", + "trim-newlines": "^3.0.0", + "type-fest": "^0.18.0", + "yargs-parser": "^20.2.3" }, "engines": { - "node": ">=16 || 14 >=14.18" + "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/isaacs" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/path-scurry/node_modules/lru-cache": { - "version": "10.2.2", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.2.tgz", - "integrity": "sha512-9hp3Vp2/hFQUiIwKo8XCeFVnrg8Pk3TYNPIR7tJADKi5YfcF7vEaK7avFHTlSy3kOKYaJQaalfEo6YuXdceBOQ==", + "node_modules/meow/node_modules/type-fest": { + "version": "0.18.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.18.1.tgz", + "integrity": "sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw==", "dev": true, + "license": "(MIT OR CC0-1.0)", "engines": { - "node": "14 || >=16.14" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/path-scurry/node_modules/minipass": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.1.tgz", - "integrity": "sha512-UZ7eQ+h8ywIRAW1hIEl2AqdwzJucU/Kp59+8kkZeSvafXhZjul247BvIJjEVFVeON6d7lM46XX1HXCduKAS8VA==", + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", "dev": true, + "license": "MIT", "engines": { - "node": ">=16 || 14 >=14.17" + "node": ">= 8" } }, - "node_modules/path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", "dev": true, + "license": "MIT", + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, "engines": { - "node": ">=8" + "node": ">=8.6" } }, - "node_modules/pathe": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", - "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", - "dev": true, - "license": "MIT", - "peer": true - }, - "node_modules/pathval": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/pathval/-/pathval-2.0.0.tgz", - "integrity": "sha512-vE7JKRyES09KiunauX7nd2Q9/L7lhok4smP9RZTDeD4MVs72Dp2qNFVz39Nz5a0FVEW0BJR6C0DYrq6unoziZA==", + "node_modules/min-indent": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", + "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", "dev": true, "license": "MIT", - "peer": true, "engines": { - "node": ">= 14.16" + "node": ">=4" } }, - "node_modules/picocolors": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", - "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", - "dev": true, - "license": "ISC" - }, - "node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, "engines": { - "node": ">=8.6" + "node": ">=16 || 14 >=14.17" }, "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/pify": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", - "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", - "dev": true, - "engines": { - "node": ">=6" + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/pirates": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", - "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==", + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", "dev": true, - "engines": { - "node": ">= 6" + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/pkg-dir": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", - "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", + "node_modules/minimist-options": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/minimist-options/-/minimist-options-4.1.0.tgz", + "integrity": "sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==", "dev": true, + "license": "MIT", "dependencies": { - "find-up": "^3.0.0" + "arrify": "^1.0.1", + "is-plain-obj": "^1.1.0", + "kind-of": "^6.0.3" }, "engines": { - "node": ">=6" + "node": ">= 6" } }, - "node_modules/pkg-dir/node_modules/find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "dev": true, - "dependencies": { - "locate-path": "^3.0.0" - }, - "engines": { - "node": ">=6" - } + "license": "MIT" }, - "node_modules/pkg-dir/node_modules/locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "node_modules/nanoid": { + "version": "3.3.11", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", + "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", "dev": true, - "dependencies": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" }, "engines": { - "node": ">=6" + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" } }, - "node_modules/pkg-dir/node_modules/p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "node_modules/nanospinner": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/nanospinner/-/nanospinner-1.2.2.tgz", + "integrity": "sha512-Zt/AmG6qRU3e+WnzGGLuMCEAO/dAu45stNbHY223tUxldaDAeE+FxSPsd9Q+j+paejmm0ZbrNVs5Sraqy3dRxA==", "dev": true, + "license": "MIT", "dependencies": { - "p-limit": "^2.0.0" - }, - "engines": { - "node": ">=6" + "picocolors": "^1.1.1" } }, - "node_modules/pkg-dir/node_modules/path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", "dev": true, - "engines": { - "node": ">=4" - } + "license": "MIT" }, - "node_modules/pkg-up": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/pkg-up/-/pkg-up-3.1.0.tgz", - "integrity": "sha512-nDywThFk1i4BQK4twPQ6TA4RT8bDY96yeuCVBWL3ePARCiEKDRSrNGbFIgUJpLp+XeIR65v8ra7WuJOFUBtkMA==", + "node_modules/normalize-package-data": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-3.0.3.tgz", + "integrity": "sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { - "find-up": "^3.0.0" + "hosted-git-info": "^4.0.1", + "is-core-module": "^2.5.0", + "semver": "^7.3.4", + "validate-npm-package-license": "^3.0.1" }, "engines": { - "node": ">=8" + "node": ">=10" } }, - "node_modules/pkg-up/node_modules/find-up": { + "node_modules/normalize-path": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", "dev": true, - "dependencies": { - "locate-path": "^3.0.0" - }, + "license": "MIT", "engines": { - "node": ">=6" + "node": ">=0.10.0" } }, - "node_modules/pkg-up/node_modules/locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "node_modules/nth-check": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", + "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" + "boolbase": "^1.0.0" }, - "engines": { - "node": ">=6" + "funding": { + "url": "https://github.com/fb55/nth-check?sponsor=1" } }, - "node_modules/pkg-up/node_modules/p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "node_modules/object-inspect": { + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", "dev": true, - "dependencies": { - "p-limit": "^2.0.0" - }, + "license": "MIT", "engines": { - "node": ">=6" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/pkg-up/node_modules/path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", "dev": true, + "license": "MIT", "engines": { - "node": ">=4" + "node": ">= 0.4" } }, - "node_modules/possible-typed-array-names": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz", - "integrity": "sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==", + "node_modules/object.assign": { + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.7.tgz", + "integrity": "sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==", "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0", + "has-symbols": "^1.1.0", + "object-keys": "^1.1.1" + }, "engines": { "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/postcss": { - "version": "8.5.3", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.3.tgz", - "integrity": "sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==", + "node_modules/object.entries": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.9.tgz", + "integrity": "sha512-8u/hfXFRBD1O0hPUjioLhoWFHRmt6tKA4/vZPyckBr18l1KE9uHrFaFaUi8MDRTpi4uak2goyPTSNJLXX2k2Hw==", "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/postcss" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], "license": "MIT", "dependencies": { - "nanoid": "^3.3.8", - "picocolors": "^1.1.1", - "source-map-js": "^1.2.1" + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.1.1" }, "engines": { - "node": "^10 || ^12 || >=14" + "node": ">= 0.4" } }, - "node_modules/postcss-resolve-nested-selector": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/postcss-resolve-nested-selector/-/postcss-resolve-nested-selector-0.1.6.tgz", - "integrity": "sha512-0sglIs9Wmkzbr8lQwEyIzlDOOC9bGmfVKcJTaxv3vMmd3uo4o4DerC3En0bnmgceeql9BfC8hRkp7cg0fjdVqw==", - "dev": true, - "license": "MIT" - }, - "node_modules/postcss-safe-parser": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/postcss-safe-parser/-/postcss-safe-parser-7.0.1.tgz", - "integrity": "sha512-0AioNCJZ2DPYz5ABT6bddIqlhgwhpHZ/l65YAYo0BCIn0xiDpsnTHz0gnoTGk0OXZW0JRs+cDwL8u/teRdz+8A==", + "node_modules/object.fromentries": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.8.tgz", + "integrity": "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==", "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/postcss-safe-parser" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0" + }, "engines": { - "node": ">=18.0" + "node": ">= 0.4" }, - "peerDependencies": { - "postcss": "^8.4.31" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/postcss-selector-parser": { - "version": "6.0.16", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.16.tgz", - "integrity": "sha512-A0RVJrX+IUkVZbW3ClroRWurercFhieevHB38sr2+l9eUClMqome3LmEmnhlNy+5Mr2EYN6B2Kaw9wYdd+VHiw==", + "node_modules/object.groupby": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.3.tgz", + "integrity": "sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==", "dev": true, + "license": "MIT", "dependencies": { - "cssesc": "^3.0.0", - "util-deprecate": "^1.0.2" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2" }, "engines": { - "node": ">=4" + "node": ">= 0.4" } }, - "node_modules/postcss-value-parser": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/prelude-ls": { + "node_modules/object.values": { "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", - "dev": true, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/punycode": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", - "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/randombytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "dev": true, - "peer": true, - "dependencies": { - "safe-buffer": "^5.1.0" - } - }, - "node_modules/readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.1.tgz", + "integrity": "sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==", "dev": true, + "license": "MIT", "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" }, "engines": { - "node": ">= 6" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/regenerate": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", - "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==", - "dev": true - }, - "node_modules/regenerate-unicode-properties": { - "version": "10.1.1", - "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.1.1.tgz", - "integrity": "sha512-X007RyZLsCJVVrjgEFVpLUTZwyOZk3oiL75ZcuYjlIWd6rNJtOjkBwQc5AsRrpbKVkxN6sklw/k/9m2jJYOf8Q==", + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", "dev": true, + "license": "ISC", "dependencies": { - "regenerate": "^1.4.2" - }, - "engines": { - "node": ">=4" + "wrappy": "1" } }, - "node_modules/regenerator-runtime": { - "version": "0.14.1", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", - "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==", - "dev": true - }, - "node_modules/regenerator-transform": { - "version": "0.15.2", - "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.2.tgz", - "integrity": "sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg==", + "node_modules/optionator": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/runtime": "^7.8.4" + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" + }, + "engines": { + "node": ">= 0.8.0" } }, - "node_modules/regexp.prototype.flags": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.2.tgz", - "integrity": "sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw==", + "node_modules/own-keys": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/own-keys/-/own-keys-1.0.1.tgz", + "integrity": "sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.6", - "define-properties": "^1.2.1", - "es-errors": "^1.3.0", - "set-function-name": "^2.0.1" + "get-intrinsic": "^1.2.6", + "object-keys": "^1.1.1", + "safe-push-apply": "^1.0.0" }, "engines": { "node": ">= 0.4" @@ -9327,589 +3926,557 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/regexpu-core": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.3.2.tgz", - "integrity": "sha512-RAM5FlZz+Lhmo7db9L298p2vHP5ZywrVXmVXpmAD9GuL5MPH6t9ROw1iA/wfHkQ76Qe7AaPF0nGuim96/IrQMQ==", + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", "dev": true, + "license": "MIT", "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" + "yocto-queue": "^0.1.0" }, "engines": { - "node": ">=4" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/regjsparser": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.9.1.tgz", - "integrity": "sha512-dQUtn90WanSNl+7mQKcXAgZxvUe7Z0SqXlgzv0za4LwiUhyzBC58yQO3liFoUgu8GiJVInAhJjkj1N0EtQ5nkQ==", + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", "dev": true, + "license": "MIT", "dependencies": { - "jsesc": "~0.5.0" + "p-limit": "^3.0.2" }, - "bin": { - "regjsparser": "bin/parser" + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/regjsparser/node_modules/jsesc": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", - "integrity": "sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==", + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", "dev": true, - "bin": { - "jsesc": "bin/jsesc" + "license": "MIT", + "engines": { + "node": ">=6" } }, - "node_modules/require-from-string": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", - "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", "dev": true, "license": "MIT", + "dependencies": { + "callsites": "^3.0.0" + }, "engines": { - "node": ">=0.10.0" + "node": ">=6" } }, - "node_modules/reselect": { - "version": "4.1.8", - "resolved": "https://registry.npmjs.org/reselect/-/reselect-4.1.8.tgz", - "integrity": "sha512-ab9EmR80F/zQTMNeneUr4cv+jSwPJgIlvEmVwLerwrWVbpLlBuls9XHzIeTFy4cegU2NHBp3va0LKOzU5qFEYQ==", - "dev": true - }, - "node_modules/resolve": { - "version": "1.22.8", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", - "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", + "node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", "dev": true, + "license": "MIT", "dependencies": { - "is-core-module": "^2.13.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" }, - "bin": { - "resolve": "bin/resolve" + "engines": { + "node": ">=8" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/resolve-from": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, - "node_modules/restore-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", - "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", "dev": true, - "dependencies": { - "onetime": "^5.1.0", - "signal-exit": "^3.0.2" - }, + "license": "MIT", "engines": { - "node": ">=8" + "node": ">=0.10.0" } }, - "node_modules/reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", "dev": true, + "license": "MIT", "engines": { - "iojs": ">=1.0.0", - "node": ">=0.10.0" + "node": ">=8" } }, - "node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } + "license": "MIT" }, - "node_modules/rimraf/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "license": "MIT", + "engines": { + "node": ">=8" } }, - "node_modules/rimraf/node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } + "license": "ISC" }, - "node_modules/rimraf/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, + "license": "MIT", "engines": { - "node": "*" + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/rollup": { - "version": "4.37.0", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.37.0.tgz", - "integrity": "sha512-iAtQy/L4QFU+rTJ1YUjXqJOJzuwEghqWzCEYD2FEghT7Gsy1VdABntrO4CLopA5IkflTyqNiLNwPcOJ3S7UKLg==", + "node_modules/possible-typed-array-names": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz", + "integrity": "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==", "dev": true, "license": "MIT", - "peer": true, - "dependencies": { - "@types/estree": "1.0.6" - }, - "bin": { - "rollup": "dist/bin/rollup" - }, - "engines": { - "node": ">=18.0.0", - "npm": ">=8.0.0" - }, - "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.37.0", - "@rollup/rollup-android-arm64": "4.37.0", - "@rollup/rollup-darwin-arm64": "4.37.0", - "@rollup/rollup-darwin-x64": "4.37.0", - "@rollup/rollup-freebsd-arm64": "4.37.0", - "@rollup/rollup-freebsd-x64": "4.37.0", - "@rollup/rollup-linux-arm-gnueabihf": "4.37.0", - "@rollup/rollup-linux-arm-musleabihf": "4.37.0", - "@rollup/rollup-linux-arm64-gnu": "4.37.0", - "@rollup/rollup-linux-arm64-musl": "4.37.0", - "@rollup/rollup-linux-loongarch64-gnu": "4.37.0", - "@rollup/rollup-linux-powerpc64le-gnu": "4.37.0", - "@rollup/rollup-linux-riscv64-gnu": "4.37.0", - "@rollup/rollup-linux-riscv64-musl": "4.37.0", - "@rollup/rollup-linux-s390x-gnu": "4.37.0", - "@rollup/rollup-linux-x64-gnu": "4.37.0", - "@rollup/rollup-linux-x64-musl": "4.37.0", - "@rollup/rollup-win32-arm64-msvc": "4.37.0", - "@rollup/rollup-win32-ia32-msvc": "4.37.0", - "@rollup/rollup-win32-x64-msvc": "4.37.0", - "fsevents": "~2.3.2" + "engines": { + "node": ">= 0.4" } }, - "node_modules/run-parallel": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", - "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "node_modules/postcss": { + "version": "8.5.6", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", + "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", "dev": true, "funding": [ { - "type": "github", - "url": "https://github.com/sponsors/feross" + "type": "opencollective", + "url": "https://opencollective.com/postcss/" }, { - "type": "patreon", - "url": "https://www.patreon.com/feross" + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" }, { - "type": "consulting", - "url": "https://feross.org/support" + "type": "github", + "url": "https://github.com/sponsors/ai" } ], + "license": "MIT", "dependencies": { - "queue-microtask": "^1.2.2" + "nanoid": "^3.3.11", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" } }, - "node_modules/safe-array-concat": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.2.tgz", - "integrity": "sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q==", + "node_modules/postcss-media-query-parser": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/postcss-media-query-parser/-/postcss-media-query-parser-0.2.3.tgz", + "integrity": "sha512-3sOlxmbKcSHMjlUXQZKQ06jOswE7oVkXPxmZdoB1r5l0q6gTFTQSHxNxOrCccElbW7dxNytifNEo8qidX2Vsig==", "dev": true, - "dependencies": { - "call-bind": "^1.0.7", - "get-intrinsic": "^1.2.4", - "has-symbols": "^1.0.3", - "isarray": "^2.0.5" - }, + "license": "MIT" + }, + "node_modules/postcss-resolve-nested-selector": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/postcss-resolve-nested-selector/-/postcss-resolve-nested-selector-0.1.6.tgz", + "integrity": "sha512-0sglIs9Wmkzbr8lQwEyIzlDOOC9bGmfVKcJTaxv3vMmd3uo4o4DerC3En0bnmgceeql9BfC8hRkp7cg0fjdVqw==", + "dev": true, + "license": "MIT" + }, + "node_modules/postcss-safe-parser": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/postcss-safe-parser/-/postcss-safe-parser-6.0.0.tgz", + "integrity": "sha512-FARHN8pwH+WiS2OPCxJI8FuRJpTVnn6ZNFiqAM2aeW2LwTHWWmWgIyKC6cUo0L8aeKiF/14MNvnpls6R2PBeMQ==", + "dev": true, + "license": "MIT", "engines": { - "node": ">=0.4" + "node": ">=12.0" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + "peerDependencies": { + "postcss": "^8.3.3" } }, - "node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "node_modules/postcss-scss": { + "version": "4.0.9", + "resolved": "https://registry.npmjs.org/postcss-scss/-/postcss-scss-4.0.9.tgz", + "integrity": "sha512-AjKOeiwAitL/MXxQW2DliT28EKukvvbEWx3LBmJIRN8KfBGZbRTxNYW0kSqi1COiTZ57nZ9NW06S6ux//N1c9A==", "dev": true, "funding": [ { - "type": "github", - "url": "https://github.com/sponsors/feross" + "type": "opencollective", + "url": "https://opencollective.com/postcss/" }, { - "type": "patreon", - "url": "https://www.patreon.com/feross" + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss-scss" }, { - "type": "consulting", - "url": "https://feross.org/support" + "type": "github", + "url": "https://github.com/sponsors/ai" } - ] + ], + "license": "MIT", + "engines": { + "node": ">=12.0" + }, + "peerDependencies": { + "postcss": "^8.4.29" + } }, - "node_modules/safe-regex-test": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.3.tgz", - "integrity": "sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==", + "node_modules/postcss-selector-parser": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz", + "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.6", - "es-errors": "^1.3.0", - "is-regex": "^1.1.4" + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=4" + } + }, + "node_modules/postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8.0" } }, - "node_modules/schema-utils": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", - "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", + "node_modules/prettier": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.6.2.tgz", + "integrity": "sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ==", "dev": true, - "peer": true, - "dependencies": { - "@types/json-schema": "^7.0.8", - "ajv": "^6.12.5", - "ajv-keywords": "^3.5.2" + "license": "MIT", + "bin": { + "prettier": "bin/prettier.cjs" }, "engines": { - "node": ">= 10.13.0" + "node": ">=14" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" + "url": "https://github.com/prettier/prettier?sponsor=1" } }, - "node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "node_modules/prettier-plugin-multiline-arrays": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/prettier-plugin-multiline-arrays/-/prettier-plugin-multiline-arrays-3.0.6.tgz", + "integrity": "sha512-FrWVa7MoDQo9b5XoLPrqIDClb0k+O8wOIsIr1DutRXhcerLY8PfIe/yYeTVD/vpRISkSXCBEYmj5Voe0wb5dEQ==", "dev": true, - "bin": { - "semver": "bin/semver.js" + "license": "(MIT or CC0 1.0)", + "dependencies": { + "@augment-vir/common": "^28.1.0", + "proxy-vir": "^1.0.0" + }, + "peerDependencies": { + "prettier": ">=3.0.0" } }, - "node_modules/serialize-javascript": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", - "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", + "node_modules/proxy-vir": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/proxy-vir/-/proxy-vir-1.0.0.tgz", + "integrity": "sha512-WV1gkBxUOwLSz0Bn09tisIqLK7leAqtFm/474t3L0hQKJw7/gdrkGcWw0/OT1PhSy+TDS6swfq7Niuoq3XJhkQ==", "dev": true, - "peer": true, + "license": "(MIT or CC0 1.0)", "dependencies": { - "randombytes": "^2.1.0" + "@augment-vir/common": "^23.3.4" } }, - "node_modules/set-function-length": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", - "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "node_modules/proxy-vir/node_modules/@augment-vir/common": { + "version": "23.4.0", + "resolved": "https://registry.npmjs.org/@augment-vir/common/-/common-23.4.0.tgz", + "integrity": "sha512-QIrJ1doD00TNbOzeVrk9KgPTzRlIjayxERnhtbQjK/AFPj5yElcB03GbnGdQZPzws/R+5gfMM5cZiH7QyBP+Kg==", "dev": true, + "license": "MIT", "dependencies": { - "define-data-property": "^1.1.4", - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.4", - "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" + "browser-or-node": "^2.1.1", + "run-time-assertions": "^1.0.0", + "type-fest": "^4.10.2" } }, - "node_modules/set-function-name": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", - "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", + "node_modules/proxy-vir/node_modules/browser-or-node": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/browser-or-node/-/browser-or-node-2.1.1.tgz", + "integrity": "sha512-8CVjaLJGuSKMVTxJ2DpBl5XnlNDiT4cQFeuCJJrvJmts9YrTZDizTX7PjC2s6W4x+MBGZeEY6dGMrF04/6Hgqg==", "dev": true, - "dependencies": { - "define-data-property": "^1.1.4", - "es-errors": "^1.3.0", - "functions-have-names": "^1.2.3", - "has-property-descriptors": "^1.0.2" - }, + "license": "MIT" + }, + "node_modules/proxy-vir/node_modules/type-fest": { + "version": "4.41.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.41.0.tgz", + "integrity": "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==", + "dev": true, + "license": "(MIT OR CC0-1.0)", "engines": { - "node": ">= 0.4" + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/shallow-clone": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", - "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", "dev": true, - "dependencies": { - "kind-of": "^6.0.2" - }, + "license": "MIT", "engines": { - "node": ">=8" + "node": ">=6" } }, - "node_modules/shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", "dev": true, - "dependencies": { - "shebang-regex": "^3.0.0" - }, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/quick-lru": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-4.0.1.tgz", + "integrity": "sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==", + "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, - "node_modules/shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "node_modules/read-pkg": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", + "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", "dev": true, + "license": "MIT", + "dependencies": { + "@types/normalize-package-data": "^2.4.0", + "normalize-package-data": "^2.5.0", + "parse-json": "^5.0.0", + "type-fest": "^0.6.0" + }, "engines": { "node": ">=8" } }, - "node_modules/side-channel": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", - "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", + "node_modules/read-pkg-up": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz", + "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.4", - "object-inspect": "^1.13.1" + "find-up": "^4.1.0", + "read-pkg": "^5.2.0", + "type-fest": "^0.8.1" }, "engines": { - "node": ">= 0.4" + "node": ">=8" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/siginfo": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz", - "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==", - "dev": true, - "license": "ISC", - "peer": true - }, - "node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true - }, - "node_modules/slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "node_modules/read-pkg-up/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, "engines": { "node": ">=8" } }, - "node_modules/slice-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", - "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", + "node_modules/read-pkg-up/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", "dev": true, "license": "MIT", "dependencies": { - "ansi-styles": "^4.0.0", - "astral-regex": "^2.0.0", - "is-fullwidth-code-point": "^3.0.0" + "p-locate": "^4.1.0" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/slice-ansi?sponsor=1" + "node": ">=8" } }, - "node_modules/slice-ansi/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "node_modules/read-pkg-up/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", "dev": true, "license": "MIT", "dependencies": { - "color-convert": "^2.0.1" + "p-try": "^2.0.0" }, "engines": { - "node": ">=8" + "node": ">=6" }, "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/slice-ansi/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "node_modules/read-pkg-up/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", "dev": true, "license": "MIT", "dependencies": { - "color-name": "~1.1.4" + "p-limit": "^2.2.0" }, "engines": { - "node": ">=7.0.0" + "node": ">=8" } }, - "node_modules/slice-ansi/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true, - "license": "MIT" - }, - "node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "node_modules/read-pkg-up/node_modules/type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", "dev": true, + "license": "(MIT OR CC0-1.0)", "engines": { - "node": ">=0.10.0" + "node": ">=8" } }, - "node_modules/source-map-js": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", - "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "node_modules/read-pkg/node_modules/hosted-git-info": { + "version": "2.8.9", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", + "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.10.0" - } + "license": "ISC" }, - "node_modules/source-map-support": { - "version": "0.5.21", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", - "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "node_modules/read-pkg/node_modules/normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" } }, - "node_modules/sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", - "dev": true - }, - "node_modules/stackback": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", - "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==", - "dev": true, - "license": "MIT", - "peer": true - }, - "node_modules/std-env": { - "version": "3.8.1", - "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.8.1.tgz", - "integrity": "sha512-vj5lIj3Mwf9D79hBkltk5qmkFI+biIKWS2IBxEyEU3AX1tUf7AoL8nSazCOiiqQsGKIq01SClsKEzweu34uwvA==", - "dev": true, - "license": "MIT", - "peer": true - }, - "node_modules/stdin-discarder": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/stdin-discarder/-/stdin-discarder-0.2.2.tgz", - "integrity": "sha512-UhDfHmA92YAlNnCfhmq0VeNL5bDbiZGg7sZ2IvPsXubGkiNa9EC+tUTsjBRsYUAz87btI6/1wf4XoVvQ3uRnmQ==", + "node_modules/read-pkg/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "license": "ISC", + "bin": { + "semver": "bin/semver" } }, - "node_modules/string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "node_modules/read-pkg/node_modules/type-fest": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", + "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", "dev": true, - "dependencies": { - "safe-buffer": "~5.2.0" + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=8" } }, - "node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "node_modules/redent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz", + "integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==", "dev": true, "license": "MIT", "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" + "indent-string": "^4.0.0", + "strip-indent": "^3.0.0" }, "engines": { "node": ">=8" } }, - "node_modules/string-width/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true, - "license": "MIT" - }, - "node_modules/string.prototype.trim": { - "version": "1.2.9", - "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.9.tgz", - "integrity": "sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw==", + "node_modules/reflect.getprototypeof": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz", + "integrity": "sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", + "call-bind": "^1.0.8", "define-properties": "^1.2.1", - "es-abstract": "^1.23.0", - "es-object-atoms": "^1.0.0" + "es-abstract": "^1.23.9", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.7", + "get-proto": "^1.0.1", + "which-builtin-type": "^1.2.1" }, "engines": { "node": ">= 0.4" @@ -9918,29 +4485,19 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/string.prototype.trimend": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.8.tgz", - "integrity": "sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-object-atoms": "^1.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/string.prototype.trimstart": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz", - "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==", + "node_modules/regexp.prototype.flags": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.4.tgz", + "integrity": "sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", + "call-bind": "^1.0.8", "define-properties": "^1.2.1", - "es-object-atoms": "^1.0.0" + "es-errors": "^1.3.0", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "set-function-name": "^2.0.2" }, "engines": { "node": ">= 0.4" @@ -9949,290 +4506,307 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", "dev": true, - "dependencies": { - "ansi-regex": "^5.0.1" - }, + "license": "MIT", "engines": { - "node": ">=8" + "node": ">=0.10.0" } }, - "node_modules/strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + "node_modules/resolve": { + "version": "1.22.11", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.11.tgz", + "integrity": "sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==", "dev": true, + "license": "MIT", + "dependencies": { + "is-core-module": "^2.16.1", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, "engines": { - "node": ">=4" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", "dev": true, + "license": "MIT", "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=4" } }, - "node_modules/stylelint": { - "version": "16.16.0", - "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-16.16.0.tgz", - "integrity": "sha512-40X5UOb/0CEFnZVEHyN260HlSSUxPES+arrUphOumGWgXERHfwCD0kNBVILgQSij8iliYVwlc0V7M5bcLP9vPg==", + "node_modules/reusify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", + "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/stylelint" - }, - { - "type": "github", - "url": "https://github.com/sponsors/stylelint" - } - ], "license": "MIT", - "dependencies": { - "@csstools/css-parser-algorithms": "^3.0.4", - "@csstools/css-tokenizer": "^3.0.3", - "@csstools/media-query-list-parser": "^4.0.2", - "@csstools/selector-specificity": "^5.0.0", - "@dual-bundle/import-meta-resolve": "^4.1.0", - "balanced-match": "^2.0.0", - "colord": "^2.9.3", - "cosmiconfig": "^9.0.0", - "css-functions-list": "^3.2.3", - "css-tree": "^3.1.0", - "debug": "^4.3.7", - "fast-glob": "^3.3.3", - "fastest-levenshtein": "^1.0.16", - "file-entry-cache": "^10.0.7", - "global-modules": "^2.0.0", - "globby": "^11.1.0", - "globjoin": "^0.1.4", - "html-tags": "^3.3.1", - "ignore": "^7.0.3", - "imurmurhash": "^0.1.4", - "is-plain-object": "^5.0.0", - "known-css-properties": "^0.35.0", - "mathml-tag-names": "^2.1.3", - "meow": "^13.2.0", - "micromatch": "^4.0.8", - "normalize-path": "^3.0.0", - "picocolors": "^1.1.1", - "postcss": "^8.5.3", - "postcss-resolve-nested-selector": "^0.1.6", - "postcss-safe-parser": "^7.0.1", - "postcss-selector-parser": "^7.1.0", - "postcss-value-parser": "^4.2.0", - "resolve-from": "^5.0.0", - "string-width": "^4.2.3", - "supports-hyperlinks": "^3.2.0", - "svg-tags": "^1.0.0", - "table": "^6.9.0", - "write-file-atomic": "^5.0.1" - }, - "bin": { - "stylelint": "bin/stylelint.mjs" - }, "engines": { - "node": ">=18.12.0" + "iojs": ">=1.0.0", + "node": ">=0.10.0" } }, - "node_modules/stylelint-define-config": { - "version": "16.15.0", - "resolved": "https://registry.npmjs.org/stylelint-define-config/-/stylelint-define-config-16.15.0.tgz", - "integrity": "sha512-nzHX9ZpI/k4A7izGYPS79xLAf2HyGvYkk/UXMgsQ7ZQEvkOZpQt4Aca4Qn5DYqNmWnqNlW5E3wK+qUmdR3vdxg==", + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "csstype": "^3.1.3" + "glob": "^7.1.3" }, - "engines": { - "node": ">=18.0.0", - "npm": ">=9.0.0", - "pnpm": ">=8.6.0" + "bin": { + "rimraf": "bin.js" }, - "peerDependencies": { - "stylelint": ">=16.0.0" + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/stylelint/node_modules/@csstools/selector-specificity": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@csstools/selector-specificity/-/selector-specificity-5.0.0.tgz", - "integrity": "sha512-PCqQV3c4CoVm3kdPhyeZ07VmBRdH2EpMFA/pd9OASpOEC3aXNGoqPDAZ80D0cLpMBxnmk0+yNhGsEx31hq7Gtw==", + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", "dev": true, "funding": [ { "type": "github", - "url": "https://github.com/sponsors/csstools" + "url": "https://github.com/sponsors/feross" }, { - "type": "opencollective", - "url": "https://opencollective.com/csstools" + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" } ], - "license": "MIT-0", - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "postcss-selector-parser": "^7.0.0" + "license": "MIT", + "dependencies": { + "queue-microtask": "^1.2.2" } }, - "node_modules/stylelint/node_modules/balanced-match": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-2.0.0.tgz", - "integrity": "sha512-1ugUSr8BHXRnK23KfuYS+gVMC3LB8QGH9W1iGtDPsNWoQbgtXSExkBu2aDR4epiGWZOjZsj6lDl/N/AqqTC3UA==", - "dev": true, - "license": "MIT" - }, - "node_modules/stylelint/node_modules/file-entry-cache": { - "version": "10.0.7", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-10.0.7.tgz", - "integrity": "sha512-txsf5fu3anp2ff3+gOJJzRImtrtm/oa9tYLN0iTuINZ++EyVR/nRrg2fKYwvG/pXDofcrvvb0scEbX3NyW/COw==", + "node_modules/run-time-assertions": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/run-time-assertions/-/run-time-assertions-1.5.2.tgz", + "integrity": "sha512-ccfwvjGuNU14cSSXLlmPRiqEgMfA7w3J2TViO79zMnzXGvE6FJ0dxnhIQGwe5r/vwySOJ4sqZksexo9wyAlA8g==", + "deprecated": "Use @augment-vir/assert instead.", "dev": true, - "license": "MIT", + "license": "(MIT or CC0 1.0)", "dependencies": { - "flat-cache": "^6.1.7" + "@augment-vir/common": "^29.3.0", + "expect-type": "~0.15.0", + "type-fest": "^4.22.0" } }, - "node_modules/stylelint/node_modules/flat-cache": { - "version": "6.1.7", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-6.1.7.tgz", - "integrity": "sha512-qwZ4xf1v1m7Rc9XiORly31YaChvKt6oNVHuqqZcoED/7O+ToyNVGobKsIAopY9ODcWpEDKEBAbrSOCBHtNQvew==", + "node_modules/run-time-assertions/node_modules/@augment-vir/common": { + "version": "29.3.0", + "resolved": "https://registry.npmjs.org/@augment-vir/common/-/common-29.3.0.tgz", + "integrity": "sha512-k3OX35/576thmGUzQUBcCKGarb7ONBfiu07+iV2vxmjl7VoB1rOB0vu8WqgB1ceJq2EMLDPXY18hHpJ9WeTHXQ==", "dev": true, "license": "MIT", "dependencies": { - "cacheable": "^1.8.9", - "flatted": "^3.3.3", - "hookified": "^1.7.1" + "browser-or-node": "^3.0.0", + "run-time-assertions": "^1.5.1", + "type-fest": "^4.21.0" } }, - "node_modules/stylelint/node_modules/ignore": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.3.tgz", - "integrity": "sha512-bAH5jbK/F3T3Jls4I0SO1hmPR0dKU0a7+SY6n1yzRtG54FLO8d6w/nxLFX2Nb7dBu6cCWXPaAME6cYqFUMmuCA==", + "node_modules/run-time-assertions/node_modules/type-fest": { + "version": "4.41.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.41.0.tgz", + "integrity": "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==", "dev": true, - "license": "MIT", + "license": "(MIT OR CC0-1.0)", "engines": { - "node": ">= 4" + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/stylelint/node_modules/is-plain-object": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", - "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", + "node_modules/safe-array-concat": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.3.tgz", + "integrity": "sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q==", "dev": true, "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.2", + "get-intrinsic": "^1.2.6", + "has-symbols": "^1.1.0", + "isarray": "^2.0.5" + }, "engines": { - "node": ">=0.10.0" + "node": ">=0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/stylelint/node_modules/postcss-selector-parser": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.0.tgz", - "integrity": "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==", + "node_modules/safe-push-apply": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/safe-push-apply/-/safe-push-apply-1.0.0.tgz", + "integrity": "sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==", "dev": true, "license": "MIT", "dependencies": { - "cssesc": "^3.0.0", - "util-deprecate": "^1.0.2" + "es-errors": "^1.3.0", + "isarray": "^2.0.5" }, "engines": { - "node": ">=4" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/stylelint/node_modules/signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "node_modules/safe-regex-test": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.1.0.tgz", + "integrity": "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==", "dev": true, - "license": "ISC", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "is-regex": "^1.2.1" + }, "engines": { - "node": ">=14" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/isaacs" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/stylelint/node_modules/write-file-atomic": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-5.0.1.tgz", - "integrity": "sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw==", + "node_modules/semver": { + "version": "7.7.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", + "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", "dev": true, "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "dev": true, + "license": "MIT", "dependencies": { - "imurmurhash": "^0.1.4", - "signal-exit": "^4.0.1" + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" }, "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": ">= 0.4" } }, - "node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "node_modules/set-function-name": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", + "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", "dev": true, + "license": "MIT", "dependencies": { - "has-flag": "^3.0.0" + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "functions-have-names": "^1.2.3", + "has-property-descriptors": "^1.0.2" }, "engines": { - "node": ">=4" + "node": ">= 0.4" } }, - "node_modules/supports-hyperlinks": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-3.2.0.tgz", - "integrity": "sha512-zFObLMyZeEwzAoKCyu1B91U79K2t7ApXuQfo8OuxwXLDgcKxuwM+YvcbIhm6QWqz7mHUH1TVytR1PwVVjEuMig==", + "node_modules/set-proto": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/set-proto/-/set-proto-1.0.0.tgz", + "integrity": "sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==", "dev": true, "license": "MIT", "dependencies": { - "has-flag": "^4.0.0", - "supports-color": "^7.0.0" + "dunder-proto": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0" }, "engines": { - "node": ">=14.18" + "node": ">= 0.4" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" }, - "funding": { - "url": "https://github.com/chalk/supports-hyperlinks?sponsor=1" + "engines": { + "node": ">=8" } }, - "node_modules/supports-hyperlinks/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", "dev": true, "license": "MIT", "engines": { "node": ">=8" } }, - "node_modules/supports-hyperlinks/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "node_modules/side-channel": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", + "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", "dev": true, "license": "MIT", "dependencies": { - "has-flag": "^4.0.0" + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3", + "side-channel-list": "^1.0.0", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" }, "engines": { - "node": ">=8" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/supports-preserve-symlinks-flag": { + "node_modules/side-channel-list": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", + "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3" + }, "engines": { "node": ">= 0.4" }, @@ -10240,422 +4814,462 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/svg-tags": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/svg-tags/-/svg-tags-1.0.0.tgz", - "integrity": "sha512-ovssysQTa+luh7A5Weu3Rta6FJlFBBbInjOh722LIt6klpU2/HtdUbszju/G4devcvk8PGt7FCLv5wftu3THUA==", - "dev": true - }, - "node_modules/table": { - "version": "6.9.0", - "resolved": "https://registry.npmjs.org/table/-/table-6.9.0.tgz", - "integrity": "sha512-9kY+CygyYM6j02t5YFHbNz2FN5QmYGv9zAjVp4lCDjlCw7amdckXlEt/bjMhUIfj4ThGRE4gCUH5+yGnNuPo5A==", + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", "dev": true, - "license": "BSD-3-Clause", + "license": "MIT", "dependencies": { - "ajv": "^8.0.1", - "lodash.truncate": "^4.4.2", - "slice-ansi": "^4.0.0", - "string-width": "^4.2.3", - "strip-ansi": "^6.0.1" + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" }, "engines": { - "node": ">=10.0.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/table/node_modules/ajv": { - "version": "8.17.1", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", - "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", "dev": true, "license": "MIT", "dependencies": { - "fast-deep-equal": "^3.1.3", - "fast-uri": "^3.0.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2" + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" }, "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/table/node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", "dev": true, - "license": "MIT" + "license": "ISC" }, - "node_modules/tapable": { - "version": "0.1.10", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-0.1.10.tgz", - "integrity": "sha512-jX8Et4hHg57mug1/079yitEKWGB3LCwoxByLsNim89LABq8NqgiX+6iYVOsq0vX8uJHkU+DZ5fnq95f800bEsQ==", + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", "dev": true, + "license": "MIT", "engines": { - "node": ">=0.6" + "node": ">=8" } }, - "node_modules/terser": { - "version": "5.31.0", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.31.0.tgz", - "integrity": "sha512-Q1JFAoUKE5IMfI4Z/lkE/E6+SwgzO+x4tq4v1AyBLRj8VSYvRO6A/rQrPg1yud4g0En9EKI1TvFRF2tQFcoUkg==", + "node_modules/slice-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", + "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", "dev": true, - "peer": true, + "license": "MIT", "dependencies": { - "@jridgewell/source-map": "^0.3.3", - "acorn": "^8.8.2", - "commander": "^2.20.0", - "source-map-support": "~0.5.20" - }, - "bin": { - "terser": "bin/terser" + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" }, "engines": { "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" } }, - "node_modules/terser-webpack-plugin": { - "version": "5.3.10", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.10.tgz", - "integrity": "sha512-BKFPWlPDndPs+NGGCr1U59t0XScL5317Y0UReNrHaw9/FwhPENlq6bfgs+4yPfyP51vqC1bQ4rp1EfXW5ZSH9w==", + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", "dev": true, - "peer": true, - "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" - }, + "license": "BSD-3-Clause", "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^5.1.0" - }, - "peerDependenciesMeta": { - "@swc/core": { - "optional": true - }, - "esbuild": { - "optional": true - }, - "uglify-js": { - "optional": true - } + "node": ">=0.10.0" } }, - "node_modules/terser-webpack-plugin/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "node_modules/spdx-correct": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz", + "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==", "dev": true, - "peer": true, - "engines": { - "node": ">=8" + "license": "Apache-2.0", + "dependencies": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" } }, - "node_modules/terser-webpack-plugin/node_modules/jest-worker": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", - "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", + "node_modules/spdx-exceptions": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz", + "integrity": "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==", + "dev": true, + "license": "CC-BY-3.0" + }, + "node_modules/spdx-expression-parse": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", "dev": true, - "peer": true, + "license": "MIT", "dependencies": { - "@types/node": "*", - "merge-stream": "^2.0.0", - "supports-color": "^8.0.0" - }, - "engines": { - "node": ">= 10.13.0" + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" } }, - "node_modules/terser-webpack-plugin/node_modules/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "node_modules/spdx-license-ids": { + "version": "3.0.22", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.22.tgz", + "integrity": "sha512-4PRT4nh1EImPbt2jASOKHX7PB7I+e4IWNLvkKFDxNhJlfjbYlleYQh285Z/3mPTHSAK/AvdMmw5BNNuYH8ShgQ==", + "dev": true, + "license": "CC0-1.0" + }, + "node_modules/stop-iteration-iterator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.1.0.tgz", + "integrity": "sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==", "dev": true, - "peer": true, + "license": "MIT", "dependencies": { - "has-flag": "^4.0.0" + "es-errors": "^1.3.0", + "internal-slot": "^1.1.0" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" + "node": ">= 0.4" } }, - "node_modules/test-exclude": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", - "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dev": true, + "license": "MIT", "dependencies": { - "@istanbuljs/schema": "^0.1.2", - "glob": "^7.1.4", - "minimatch": "^3.0.4" + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" }, "engines": { "node": ">=8" } }, - "node_modules/test-exclude/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "node_modules/string-width/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } + "license": "MIT" }, - "node_modules/test-exclude/node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "node_modules/string.prototype.trim": { + "version": "1.2.10", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.10.tgz", + "integrity": "sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA==", "dev": true, + "license": "MIT", "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" + "call-bind": "^1.0.8", + "call-bound": "^1.0.2", + "define-data-property": "^1.1.4", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-object-atoms": "^1.0.0", + "has-property-descriptors": "^1.0.2" }, "engines": { - "node": "*" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/isaacs" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/test-exclude/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "node_modules/string.prototype.trimend": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.9.tgz", + "integrity": "sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ==", "dev": true, + "license": "MIT", "dependencies": { - "brace-expansion": "^1.1.7" + "call-bind": "^1.0.8", + "call-bound": "^1.0.2", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" }, "engines": { - "node": "*" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", - "dev": true - }, - "node_modules/tinybench": { - "version": "2.9.0", - "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz", - "integrity": "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==", + "node_modules/string.prototype.trimstart": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz", + "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==", "dev": true, "license": "MIT", - "peer": true + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, - "node_modules/tinyexec": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-0.3.2.tgz", - "integrity": "sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==", + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, "license": "MIT", - "peer": true + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } }, - "node_modules/tinypool": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-1.0.2.tgz", - "integrity": "sha512-al6n+QEANGFOMf/dmUMsuS5/r9B06uwlyNjZZql/zv8J7ybHCgoihBNORZCY2mzUuAnomQa2JdhyHKzZxPCrFA==", + "node_modules/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", "dev": true, "license": "MIT", - "peer": true, "engines": { - "node": "^18.0.0 || >=20.0.0" + "node": ">=4" } }, - "node_modules/tinyrainbow": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-2.0.0.tgz", - "integrity": "sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw==", + "node_modules/strip-indent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", + "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", "dev": true, "license": "MIT", - "peer": true, + "dependencies": { + "min-indent": "^1.0.0" + }, "engines": { - "node": ">=14.0.0" + "node": ">=8" } }, - "node_modules/tinyspy": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-3.0.2.tgz", - "integrity": "sha512-n1cw8k1k0x4pgA2+9XrOkFydTerNcJ1zWCO5Nn9scWHTD+5tp8dghT2x1uduQePZTZgd3Tupf+x9BxJjeJi77Q==", + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", "dev": true, "license": "MIT", - "peer": true, "engines": { - "node": ">=14.0.0" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/tmpl": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", - "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", - "dev": true - }, - "node_modules/to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", + "node_modules/style-search": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/style-search/-/style-search-0.1.0.tgz", + "integrity": "sha512-Dj1Okke1C3uKKwQcetra4jSuk0DqbzbYtXipzFlFMZtowbF1x7BKJwB9AayVMyFARvU8EDrZdcax4At/452cAg==", "dev": true, - "engines": { - "node": ">=4" - } + "license": "ISC" }, - "node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "node_modules/stylelint": { + "version": "14.16.1", + "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-14.16.1.tgz", + "integrity": "sha512-ErlzR/T3hhbV+a925/gbfc3f3Fep9/bnspMiJPorfGEmcBbXdS+oo6LrVtoUZ/w9fqD6o6k7PtUlCOsCRdjX/A==", "dev": true, "license": "MIT", "dependencies": { - "is-number": "^7.0.0" + "@csstools/selector-specificity": "^2.0.2", + "balanced-match": "^2.0.0", + "colord": "^2.9.3", + "cosmiconfig": "^7.1.0", + "css-functions-list": "^3.1.0", + "debug": "^4.3.4", + "fast-glob": "^3.2.12", + "fastest-levenshtein": "^1.0.16", + "file-entry-cache": "^6.0.1", + "global-modules": "^2.0.0", + "globby": "^11.1.0", + "globjoin": "^0.1.4", + "html-tags": "^3.2.0", + "ignore": "^5.2.1", + "import-lazy": "^4.0.0", + "imurmurhash": "^0.1.4", + "is-plain-object": "^5.0.0", + "known-css-properties": "^0.26.0", + "mathml-tag-names": "^2.1.3", + "meow": "^9.0.0", + "micromatch": "^4.0.5", + "normalize-path": "^3.0.0", + "picocolors": "^1.0.0", + "postcss": "^8.4.19", + "postcss-media-query-parser": "^0.2.3", + "postcss-resolve-nested-selector": "^0.1.1", + "postcss-safe-parser": "^6.0.0", + "postcss-selector-parser": "^6.0.11", + "postcss-value-parser": "^4.2.0", + "resolve-from": "^5.0.0", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "style-search": "^0.1.0", + "supports-hyperlinks": "^2.3.0", + "svg-tags": "^1.0.0", + "table": "^6.8.1", + "v8-compile-cache": "^2.3.0", + "write-file-atomic": "^4.0.2" + }, + "bin": { + "stylelint": "bin/stylelint.js" }, "engines": { - "node": ">=8.0" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/stylelint" } }, - "node_modules/ts-api-utils": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.3.0.tgz", - "integrity": "sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==", + "node_modules/stylelint-config-recommended": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/stylelint-config-recommended/-/stylelint-config-recommended-8.0.0.tgz", + "integrity": "sha512-IK6dWvE000+xBv9jbnHOnBq01gt6HGVB2ZTsot+QsMpe82doDQ9hvplxfv4YnpEuUwVGGd9y6nbaAnhrjcxhZQ==", "dev": true, - "engines": { - "node": ">=16" + "license": "MIT", + "peerDependencies": { + "stylelint": "^14.8.0" + } + }, + "node_modules/stylelint-config-recommended-scss": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/stylelint-config-recommended-scss/-/stylelint-config-recommended-scss-7.0.0.tgz", + "integrity": "sha512-rGz1J4rMAyJkvoJW4hZasuQBB7y9KIrShb20l9DVEKKZSEi1HAy0vuNlR8HyCKy/jveb/BdaQFcoiYnmx4HoiA==", + "dev": true, + "license": "MIT", + "dependencies": { + "postcss-scss": "^4.0.2", + "stylelint-config-recommended": "^8.0.0", + "stylelint-scss": "^4.0.0" }, "peerDependencies": { - "typescript": ">=4.2.0" + "stylelint": "^14.4.0" } }, - "node_modules/tsconfig-paths": { - "version": "3.15.0", - "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", - "integrity": "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==", + "node_modules/stylelint-config-standard": { + "version": "26.0.0", + "resolved": "https://registry.npmjs.org/stylelint-config-standard/-/stylelint-config-standard-26.0.0.tgz", + "integrity": "sha512-hUuB7LaaqM8abvkOO84wh5oYSkpXgTzHu2Zza6e7mY+aOmpNTjoFBRxSLlzY0uAOMWEFx0OMKzr+reG1BUtcqQ==", "dev": true, + "license": "MIT", "dependencies": { - "@types/json5": "^0.0.29", - "json5": "^1.0.2", - "minimist": "^1.2.6", - "strip-bom": "^3.0.0" + "stylelint-config-recommended": "^8.0.0" + }, + "peerDependencies": { + "stylelint": "^14.9.0" } }, - "node_modules/tsconfig-paths/node_modules/json5": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", - "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", + "node_modules/stylelint-config-standard-scss": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/stylelint-config-standard-scss/-/stylelint-config-standard-scss-5.0.0.tgz", + "integrity": "sha512-zoXLibojHZYPFjtkc4STZtAJ2yGTq3Bb4MYO0oiyO6f/vNxDKRcSDZYoqN260Gv2eD5niQIr1/kr5SXlFj9kcQ==", "dev": true, + "license": "MIT", "dependencies": { - "minimist": "^1.2.0" + "stylelint-config-recommended-scss": "^7.0.0", + "stylelint-config-standard": "^26.0.0" }, - "bin": { - "json5": "lib/cli.js" + "peerDependencies": { + "stylelint": "^14.9.0" } }, - "node_modules/type-check": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "node_modules/stylelint-junit-formatter": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/stylelint-junit-formatter/-/stylelint-junit-formatter-0.2.2.tgz", + "integrity": "sha512-8Yx0sG5vYKf+wBbFKibbuiuydKezBwo2M9svoNYtvYTKvSiMYVhZSvVJh9hMAWeSPImcVP9OwTq+Ku/00j9/Ng==", "dev": true, + "license": "MIT", "dependencies": { - "prelude-ls": "^1.2.1" - }, - "engines": { - "node": ">= 0.8.0" + "xmlbuilder": "^13.0.2" } }, - "node_modules/type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "node_modules/stylelint-scss": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/stylelint-scss/-/stylelint-scss-4.7.0.tgz", + "integrity": "sha512-TSUgIeS0H3jqDZnby1UO1Qv3poi1N8wUYIJY6D1tuUq2MN3lwp/rITVo0wD+1SWTmRm0tNmGO0b7nKInnqF6Hg==", "dev": true, - "engines": { - "node": ">=10" + "license": "MIT", + "dependencies": { + "postcss-media-query-parser": "^0.2.3", + "postcss-resolve-nested-selector": "^0.1.1", + "postcss-selector-parser": "^6.0.11", + "postcss-value-parser": "^4.2.0" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "peerDependencies": { + "stylelint": "^14.5.1 || ^15.0.0" } }, - "node_modules/typed-array-buffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.2.tgz", - "integrity": "sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ==", + "node_modules/stylelint/node_modules/balanced-match": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-2.0.0.tgz", + "integrity": "sha512-1ugUSr8BHXRnK23KfuYS+gVMC3LB8QGH9W1iGtDPsNWoQbgtXSExkBu2aDR4epiGWZOjZsj6lDl/N/AqqTC3UA==", "dev": true, - "dependencies": { - "call-bind": "^1.0.7", - "es-errors": "^1.3.0", - "is-typed-array": "^1.1.13" - }, + "license": "MIT" + }, + "node_modules/stylelint/node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true, + "license": "MIT", "engines": { - "node": ">= 0.4" + "node": ">=8" } }, - "node_modules/typed-array-byte-length": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.1.tgz", - "integrity": "sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw==", + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-proto": "^1.0.3", - "is-typed-array": "^1.1.13" + "has-flag": "^4.0.0" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=8" } }, - "node_modules/typed-array-byte-offset": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.2.tgz", - "integrity": "sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA==", + "node_modules/supports-hyperlinks": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-2.3.0.tgz", + "integrity": "sha512-RpsAZlpWcDwOPQA22aCH4J0t7L8JmAvsCxfOSEwm7cQs3LshN36QaTkwd70DnBOXDWGssw2eUoc8CaRWT0XunA==", "dev": true, + "license": "MIT", "dependencies": { - "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.7", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-proto": "^1.0.3", - "is-typed-array": "^1.1.13" + "has-flag": "^4.0.0", + "supports-color": "^7.0.0" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=8" } }, - "node_modules/typed-array-length": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.6.tgz", - "integrity": "sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g==", + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", "dev": true, - "dependencies": { - "call-bind": "^1.0.7", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-proto": "^1.0.3", - "is-typed-array": "^1.1.13", - "possible-typed-array-names": "^1.0.0" - }, + "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -10663,479 +5277,326 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/typescript": { - "version": "5.4.5", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.5.tgz", - "integrity": "sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==", + "node_modules/svg-tags": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/svg-tags/-/svg-tags-1.0.0.tgz", + "integrity": "sha512-ovssysQTa+luh7A5Weu3Rta6FJlFBBbInjOh722LIt6klpU2/HtdUbszju/G4devcvk8PGt7FCLv5wftu3THUA==", + "dev": true + }, + "node_modules/table": { + "version": "6.9.0", + "resolved": "https://registry.npmjs.org/table/-/table-6.9.0.tgz", + "integrity": "sha512-9kY+CygyYM6j02t5YFHbNz2FN5QmYGv9zAjVp4lCDjlCw7amdckXlEt/bjMhUIfj4ThGRE4gCUH5+yGnNuPo5A==", "dev": true, - "peer": true, - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" + "license": "BSD-3-Clause", + "dependencies": { + "ajv": "^8.0.1", + "lodash.truncate": "^4.4.2", + "slice-ansi": "^4.0.0", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1" }, "engines": { - "node": ">=14.17" + "node": ">=10.0.0" } }, - "node_modules/unbox-primitive": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", - "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", + "node_modules/table/node_modules/ajv": { + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", + "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "has-bigints": "^1.0.2", - "has-symbols": "^1.0.3", - "which-boxed-primitive": "^1.0.2" + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" } }, - "node_modules/undici-types": { - "version": "5.26.5", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", - "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", - "dev": true + "node_modules/table/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true, + "license": "MIT" }, - "node_modules/unicode-canonical-property-names-ecmascript": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz", - "integrity": "sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==", + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", "dev": true, - "engines": { - "node": ">=4" - } + "license": "MIT" }, - "node_modules/unicode-match-property-ecmascript": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz", - "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==", + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", "dev": true, + "license": "MIT", "dependencies": { - "unicode-canonical-property-names-ecmascript": "^2.0.0", - "unicode-property-aliases-ecmascript": "^2.0.0" + "is-number": "^7.0.0" }, "engines": { - "node": ">=4" + "node": ">=8.0" } }, - "node_modules/unicode-match-property-value-ecmascript": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.1.0.tgz", - "integrity": "sha512-qxkjQt6qjg/mYscYMC0XKRn3Rh0wFPlfxB0xkt9CfyTvpX1Ra0+rAmdX2QyAobptSEvuy4RtpPRui6XkV+8wjA==", + "node_modules/trim-newlines": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-3.0.1.tgz", + "integrity": "sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==", "dev": true, + "license": "MIT", "engines": { - "node": ">=4" + "node": ">=8" } }, - "node_modules/unicode-property-aliases-ecmascript": { + "node_modules/ts-api-utils": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz", - "integrity": "sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.1.0.tgz", + "integrity": "sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==", "dev": true, + "license": "MIT", "engines": { - "node": ">=4" - } - }, - "node_modules/update-browserslist-db": { - "version": "1.0.16", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.16.tgz", - "integrity": "sha512-KVbTxlBYlckhF5wgfyZXTWnMn7MMZjMu9XG8bPlliUOP9ThaF4QnhP8qrjrH7DRzHfSk0oQv1wToW+iA5GajEQ==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "dependencies": { - "escalade": "^3.1.2", - "picocolors": "^1.0.1" - }, - "bin": { - "update-browserslist-db": "cli.js" + "node": ">=18.12" }, "peerDependencies": { - "browserslist": ">= 4.21.0" - } - }, - "node_modules/uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dev": true, - "dependencies": { - "punycode": "^2.1.0" + "typescript": ">=4.8.4" } }, - "node_modules/util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", - "dev": true - }, - "node_modules/vite": { - "version": "6.2.3", - "resolved": "https://registry.npmjs.org/vite/-/vite-6.2.3.tgz", - "integrity": "sha512-IzwM54g4y9JA/xAeBPNaDXiBF8Jsgl3VBQ2YQ/wOY6fyW3xMdSoltIV3Bo59DErdqdE6RxUfv8W69DvUorE4Eg==", + "node_modules/tsconfig-paths": { + "version": "3.15.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", + "integrity": "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { - "esbuild": "^0.25.0", - "postcss": "^8.5.3", - "rollup": "^4.30.1" - }, - "bin": { - "vite": "bin/vite.js" - }, - "engines": { - "node": "^18.0.0 || ^20.0.0 || >=22.0.0" - }, - "funding": { - "url": "https://github.com/vitejs/vite?sponsor=1" - }, - "optionalDependencies": { - "fsevents": "~2.3.3" - }, - "peerDependencies": { - "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", - "jiti": ">=1.21.0", - "less": "*", - "lightningcss": "^1.21.0", - "sass": "*", - "sass-embedded": "*", - "stylus": "*", - "sugarss": "*", - "terser": "^5.16.0", - "tsx": "^4.8.1", - "yaml": "^2.4.2" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - }, - "jiti": { - "optional": true - }, - "less": { - "optional": true - }, - "lightningcss": { - "optional": true - }, - "sass": { - "optional": true - }, - "sass-embedded": { - "optional": true - }, - "stylus": { - "optional": true - }, - "sugarss": { - "optional": true - }, - "terser": { - "optional": true - }, - "tsx": { - "optional": true - }, - "yaml": { - "optional": true - } + "@types/json5": "^0.0.29", + "json5": "^1.0.2", + "minimist": "^1.2.6", + "strip-bom": "^3.0.0" } }, - "node_modules/vite-node": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-3.0.9.tgz", - "integrity": "sha512-w3Gdx7jDcuT9cNn9jExXgOyKmf5UOTb6WMHz8LGAm54eS1Elf5OuBhCxl6zJxGhEeIkgsE1WbHuoL0mj/UXqXg==", + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { - "cac": "^6.7.14", - "debug": "^4.4.0", - "es-module-lexer": "^1.6.0", - "pathe": "^2.0.3", - "vite": "^5.0.0 || ^6.0.0" - }, - "bin": { - "vite-node": "vite-node.mjs" + "prelude-ls": "^1.2.1" }, "engines": { - "node": "^18.0.0 || ^20.0.0 || >=22.0.0" + "node": ">= 0.8.0" + } + }, + "node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=10" }, "funding": { - "url": "https://opencollective.com/vitest" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/vitest": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/vitest/-/vitest-3.0.9.tgz", - "integrity": "sha512-BbcFDqNyBlfSpATmTtXOAOj71RNKDDvjBM/uPfnxxVGrG+FSH2RQIwgeEngTaTkuU/h0ScFvf+tRcKfYXzBybQ==", + "node_modules/typed-array-buffer": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz", + "integrity": "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { - "@vitest/expect": "3.0.9", - "@vitest/mocker": "3.0.9", - "@vitest/pretty-format": "^3.0.9", - "@vitest/runner": "3.0.9", - "@vitest/snapshot": "3.0.9", - "@vitest/spy": "3.0.9", - "@vitest/utils": "3.0.9", - "chai": "^5.2.0", - "debug": "^4.4.0", - "expect-type": "^1.1.0", - "magic-string": "^0.30.17", - "pathe": "^2.0.3", - "std-env": "^3.8.0", - "tinybench": "^2.9.0", - "tinyexec": "^0.3.2", - "tinypool": "^1.0.2", - "tinyrainbow": "^2.0.0", - "vite": "^5.0.0 || ^6.0.0", - "vite-node": "3.0.9", - "why-is-node-running": "^2.3.0" - }, - "bin": { - "vitest": "vitest.mjs" + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-typed-array": "^1.1.14" }, "engines": { - "node": "^18.0.0 || ^20.0.0 || >=22.0.0" - }, - "funding": { - "url": "https://opencollective.com/vitest" - }, - "peerDependencies": { - "@edge-runtime/vm": "*", - "@types/debug": "^4.1.12", - "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", - "@vitest/browser": "3.0.9", - "@vitest/ui": "3.0.9", - "happy-dom": "*", - "jsdom": "*" - }, - "peerDependenciesMeta": { - "@edge-runtime/vm": { - "optional": true - }, - "@types/debug": { - "optional": true - }, - "@types/node": { - "optional": true - }, - "@vitest/browser": { - "optional": true - }, - "@vitest/ui": { - "optional": true - }, - "happy-dom": { - "optional": true - }, - "jsdom": { - "optional": true - } + "node": ">= 0.4" } }, - "node_modules/vue-eslint-parser": { - "version": "9.4.2", - "resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-9.4.2.tgz", - "integrity": "sha512-Ry9oiGmCAK91HrKMtCrKFWmSFWvYkpGglCeFAIqDdr9zdXmMMpJOmUJS7WWsW7fX81h6mwHmUZCQQ1E0PkSwYQ==", + "node_modules/typed-array-byte-length": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.3.tgz", + "integrity": "sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==", "dev": true, + "license": "MIT", "dependencies": { - "debug": "^4.3.4", - "eslint-scope": "^7.1.1", - "eslint-visitor-keys": "^3.3.0", - "espree": "^9.3.1", - "esquery": "^1.4.0", - "lodash": "^4.17.21", - "semver": "^7.3.6" + "call-bind": "^1.0.8", + "for-each": "^0.3.3", + "gopd": "^1.2.0", + "has-proto": "^1.2.0", + "is-typed-array": "^1.1.14" }, "engines": { - "node": "^14.17.0 || >=16.0.0" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/mysticatea" - }, - "peerDependencies": { - "eslint": ">=6.0.0" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/vue-eslint-parser/node_modules/eslint-scope": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", - "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "node_modules/typed-array-byte-offset": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.4.tgz", + "integrity": "sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==", "dev": true, + "license": "MIT", "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "for-each": "^0.3.3", + "gopd": "^1.2.0", + "has-proto": "^1.2.0", + "is-typed-array": "^1.1.15", + "reflect.getprototypeof": "^1.0.9" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": ">= 0.4" }, "funding": { - "url": "https://opencollective.com/eslint" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/vue-eslint-parser/node_modules/eslint-visitor-keys": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", - "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "node_modules/typed-array-length": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.7.tgz", + "integrity": "sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==", "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "is-typed-array": "^1.1.13", + "possible-typed-array-names": "^1.0.0", + "reflect.getprototypeof": "^1.0.6" + }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": ">= 0.4" }, "funding": { - "url": "https://opencollective.com/eslint" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/vue-eslint-parser/node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "node_modules/typescript": { + "version": "5.7.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.7.3.tgz", + "integrity": "sha512-84MVSjMEHP+FQRPy3pX9sTVV/INIex71s9TL2Gm5FG/WG1SqXeKyZ0k7/blY/4FdOzI12CBy1vGc4og/eus0fw==", "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, "engines": { - "node": ">=4.0" + "node": ">=14.17" } }, - "node_modules/vue-eslint-parser/node_modules/semver": { - "version": "7.6.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", - "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", + "node_modules/unbox-primitive": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.1.0.tgz", + "integrity": "sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==", "dev": true, - "bin": { - "semver": "bin/semver.js" + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "has-bigints": "^1.0.2", + "has-symbols": "^1.1.0", + "which-boxed-primitive": "^1.1.1" }, "engines": { - "node": ">=10" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/walker": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", - "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { - "makeerror": "1.0.12" + "punycode": "^2.1.0" } }, - "node_modules/watchpack": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.1.tgz", - "integrity": "sha512-8wrBCMtVhqcXP2Sup1ctSkga6uc2Bx0IIvKyT7yTFier5AXHooSI+QyQQAtTb7+E0IUCCKyTFmXqdqgum2XWGg==", + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", "dev": true, - "peer": true, + "license": "MIT" + }, + "node_modules/v8-compile-cache": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.4.0.tgz", + "integrity": "sha512-ocyWc3bAHBB/guyqJQVI5o4BZkPhznPYUG2ea80Gond/BgNWpap8TOmLSeeQG7bnh2KMISxskdADG59j7zruhw==", + "dev": true, + "license": "MIT" + }, + "node_modules/validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "dev": true, + "license": "Apache-2.0", "dependencies": { - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.1.2" - }, - "engines": { - "node": ">=10.13.0" + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" } }, - "node_modules/wcwidth": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", - "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==", - "dev": true, - "dependencies": { - "defaults": "^1.0.3" - } - }, - "node_modules/webpack": { - "version": "5.91.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.91.0.tgz", - "integrity": "sha512-rzVwlLeBWHJbmgTC/8TvAcu5vpJNII+MelQpylD4jNERPwpBJOE2lEcko1zJX3QJeLjTTAnQxn/OJ8bjDzVQaw==", - "dev": true, - "peer": true, - "dependencies": { - "@types/eslint-scope": "^3.7.3", - "@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-assertions": "^1.9.0", - "browserslist": "^4.21.10", - "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.16.0", - "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" - }, - "bin": { - "webpack": "bin/webpack.js" - }, - "engines": { - "node": ">=10.13.0" + "node_modules/vue": { + "version": "3.5.22", + "resolved": "https://registry.npmjs.org/vue/-/vue-3.5.22.tgz", + "integrity": "sha512-toaZjQ3a/G/mYaLSbV+QsQhIdMo9x5rrqIpYRObsJ6T/J+RyCSFwN2LHNVH9v8uIcljDNa3QzPVdv3Y6b9hAJQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vue/compiler-dom": "3.5.22", + "@vue/compiler-sfc": "3.5.22", + "@vue/runtime-dom": "3.5.22", + "@vue/server-renderer": "3.5.22", + "@vue/shared": "3.5.22" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" + "peerDependencies": { + "typescript": "*" }, "peerDependenciesMeta": { - "webpack-cli": { + "typescript": { "optional": true } } }, - "node_modules/webpack-sources": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz", - "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==", - "dev": true, - "peer": true, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/webpack/node_modules/enhanced-resolve": { - "version": "5.16.1", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.16.1.tgz", - "integrity": "sha512-4U5pNsuDl0EhuZpq46M5xPslstkviJuhrdobaRDBk2Jy2KO37FDAJl4lb2KlNabxT0m4MTK2UHNrsAcphE8nyw==", + "node_modules/vue-eslint-parser": { + "version": "9.4.3", + "resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-9.4.3.tgz", + "integrity": "sha512-2rYRLWlIpaiN8xbPiDyXZXRgLGOtWxERV7ND5fFAv5qo1D2N9Fu9MNajBNc6o13lZ+24DAWCkQCvj4klgmcITg==", "dev": true, - "peer": true, + "license": "MIT", "dependencies": { - "graceful-fs": "^4.2.4", - "tapable": "^2.2.0" + "debug": "^4.3.4", + "eslint-scope": "^7.1.1", + "eslint-visitor-keys": "^3.3.0", + "espree": "^9.3.1", + "esquery": "^1.4.0", + "lodash": "^4.17.21", + "semver": "^7.3.6" }, "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/webpack/node_modules/tapable": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", - "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", - "dev": true, - "peer": true, - "engines": { - "node": ">=6" + "node": "^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + }, + "peerDependencies": { + "eslint": ">=6.0.0" } }, "node_modules/which": { @@ -11143,6 +5604,7 @@ "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", "dev": true, + "license": "ISC", "dependencies": { "isexe": "^2.0.0" }, @@ -11154,32 +5616,45 @@ } }, "node_modules/which-boxed-primitive": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", - "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.1.1.tgz", + "integrity": "sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==", "dev": true, + "license": "MIT", "dependencies": { - "is-bigint": "^1.0.1", - "is-boolean-object": "^1.1.0", - "is-number-object": "^1.0.4", - "is-string": "^1.0.5", - "is-symbol": "^1.0.3" + "is-bigint": "^1.1.0", + "is-boolean-object": "^1.2.1", + "is-number-object": "^1.1.1", + "is-string": "^1.1.1", + "is-symbol": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/which-typed-array": { - "version": "1.1.15", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.15.tgz", - "integrity": "sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==", + "node_modules/which-builtin-type": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.2.1.tgz", + "integrity": "sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q==", "dev": true, + "license": "MIT", "dependencies": { - "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.7", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-tostringtag": "^1.0.2" + "call-bound": "^1.0.2", + "function.prototype.name": "^1.1.6", + "has-tostringtag": "^1.0.2", + "is-async-function": "^2.0.0", + "is-date-object": "^1.1.0", + "is-finalizationregistry": "^1.1.0", + "is-generator-function": "^1.0.10", + "is-regex": "^1.2.1", + "is-weakref": "^1.0.2", + "isarray": "^2.0.5", + "which-boxed-primitive": "^1.1.0", + "which-collection": "^1.0.2", + "which-typed-array": "^1.1.16" }, "engines": { "node": ">= 0.4" @@ -11188,22 +5663,45 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/why-is-node-running": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.3.0.tgz", - "integrity": "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==", + "node_modules/which-collection": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz", + "integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { - "siginfo": "^2.0.0", - "stackback": "0.0.2" + "is-map": "^2.0.3", + "is-set": "^2.0.3", + "is-weakmap": "^2.0.2", + "is-weakset": "^2.0.3" }, - "bin": { - "why-is-node-running": "cli.js" + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-typed-array": { + "version": "1.1.19", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.19.tgz", + "integrity": "sha512-rEvr90Bck4WZt9HHFC4DJMsjvu7x+r6bImz0/BrbWb7A2djJ8hnZMrWnHo9F8ssv0OMErasDhftrfROTyqSDrw==", + "dev": true, + "license": "MIT", + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "for-each": "^0.3.5", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2" }, "engines": { - "node": ">=8" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/word-wrap": { @@ -11211,6 +5709,7 @@ "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -11219,13 +5718,15 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/write-file-atomic": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz", "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==", "dev": true, + "license": "ISC", "dependencies": { "imurmurhash": "^0.1.4", "signal-exit": "^3.0.7" @@ -11239,38 +5740,60 @@ "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-4.0.0.tgz", "integrity": "sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==", "dev": true, + "license": "Apache-2.0", "engines": { "node": ">=12" } }, + "node_modules/xmlbuilder": { + "version": "13.0.2", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-13.0.2.tgz", + "integrity": "sha512-Eux0i2QdDYKbdbA6AM6xE4m6ZTZr4G4xF9kahI2ukSEMCzwce2eX9WlTI5J3s+NU7hpasFsr8hWIONae7LluAQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0" + } + }, "node_modules/yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", - "dev": true + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true, + "license": "ISC" + }, + "node_modules/yaml": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", + "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">= 6" + } + }, + "node_modules/yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=10" + } }, "node_modules/yocto-queue": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } - }, - "node_modules/zod": { - "version": "3.24.2", - "resolved": "https://registry.npmjs.org/zod/-/zod-3.24.2.tgz", - "integrity": "sha512-lY7CDW43ECgW9u1TcT3IoXHflywfVqDYze4waEz812jR/bZ8FHDsl7pFQoSZTz5N+2NqRXs8GBwnAwo3ZNxqhQ==", - "dev": true, - "license": "MIT", - "peer": true, - "funding": { - "url": "https://github.com/sponsors/colinhacks" - } } } } diff --git a/src/Resources/app/administration/package.json b/src/Resources/app/administration/package.json index 222036e48..5b82b4b2d 100644 --- a/src/Resources/app/administration/package.json +++ b/src/Resources/app/administration/package.json @@ -1,56 +1,39 @@ { - "name": "swagmigrationassistant", - "version": "1.0.0", - "description": "Migrate shop data to Shopware 6", - "main": "index.js", + "name": "swag-migration-assistant", + "description": "Plugin for migrating data to Shopware 6", "author": "shopware AG", "license": "MIT", "scripts": { "lint": "eslint --ext .js,.ts,.vue,.html,.html.twig .", - "lint-fix": "npm run lint -- --fix", + "lint:fix": "npm run lint -- --fix", "lint:scss": "stylelint ./**/*.scss", - "lint:scss-fix": "npm run lint:scss -- --fix" + "lint:scss:fix": "npm run lint:scss -- --fix", + "format": "prettier --check \"src/**/*.{js,ts}\" --config ../../../../.prettierrc.json --cache", + "format:fix": "prettier --write \"src/**/*.{js,ts}\" --config ../../../../.prettierrc.json --cache", + "format:md": "prettier --check \"../../../../*.md\" --config ../../../../.prettierrc.json --cache", + "format:md:fix": "prettier --write \"../../../../*.md\" --config ../../../../.prettierrc.json --cache" }, "devDependencies": { - "@babel/core": "^7.24.5", - "@babel/eslint-parser": "^7.24.5", - "@babel/plugin-proposal-class-properties": "^7.18.6", - "@babel/plugin-proposal-decorators": "^7.24.1", - "@babel/plugin-proposal-export-namespace-from": "^7.18.9", - "@babel/plugin-proposal-function-sent": "^7.24.1", - "@babel/plugin-proposal-json-strings": "^7.18.6", - "@babel/plugin-proposal-numeric-separator": "^7.18.6", - "@babel/plugin-proposal-throw-expressions": "^7.24.1", - "@babel/plugin-syntax-dynamic-import": "^7.8.3", - "@babel/plugin-syntax-import-meta": "^7.10.4", - "@babel/plugin-transform-runtime": "^7.24.3", - "@babel/preset-env": "^7.24.5", - "@babel/preset-typescript": "^7.24.1", - "@babel/register": "^7.23.7", - "@shopware-ag/eslint-config-base": "^2.0.0", - "@shopware-ag/stylelint-plugin-meteor": "^1.1.0", - "@typescript-eslint/eslint-plugin": "^7.9.0", - "@typescript-eslint/parser": "^7.9.0", - "babel-jest": "^29.7.0", - "babel-plugin-istanbul": "^6.1.1", - "babel-plugin-module-resolver": "^5.0.2", - "core-js": "^2.6.12", - "eslint": "^8.57.0", - "eslint-import-resolver-webpack": "^0.13.8", - "eslint-plugin-file-progress": "^1.4.0", - "eslint-plugin-filename-rules": "^1.3.1", - "eslint-plugin-html": "^8.1.1", - "eslint-plugin-inclusive-language": "^2.2.1", - "eslint-plugin-jest": "^28.5.0", - "eslint-plugin-plugin-rules": "file:../../../../../../../src/Administration/Resources/app/administration/eslint-rules/plugin-rules", - "eslint-plugin-simple-import-sort": "^12.1.0", - "eslint-plugin-sw-core-rules": "file:../../../../../../../src/Administration/Resources/app/administration/eslint-rules/core-rules", - "eslint-plugin-sw-deprecation-rules": "file:../../../../../../../src/Administration/Resources/app/administration/eslint-rules/deprecation-rules", - "eslint-plugin-sw-test-rules": "file:../../../../../../../src/Administration/Resources/app/administration/eslint-rules/test-rules", - "eslint-plugin-twig-vue": "file:../../../../../../../src/Administration/Resources/app/administration/twigVuePlugin", - "eslint-plugin-vue": "^9.26.0", - "eslint-plugin-vuejs-accessibility": "^2.3.0", - "stylelint": "^16.16.0", - "stylelint-define-config": "^16.15.0" + "@shopware-ag/eslint-config-base": "2.0.0", + "@typescript-eslint/eslint-plugin": "8.21.0", + "@typescript-eslint/parser": "8.21.0", + "eslint": "8.57.1", + "eslint-config-prettier": "9.1.0", + "eslint-plugin-file-progress": "1.5.0", + "eslint-plugin-filename-rules": "1.3.1", + "eslint-plugin-html": "7.1.0", + "eslint-plugin-import": "2.31.0", + "eslint-plugin-inclusive-language": "2.2.1", + "eslint-plugin-vue": "9.32.0", + "eslint-plugin-vuejs-accessibility": "2.4.1", + "prettier": "3.6.2", + "prettier-plugin-multiline-arrays": "3.0.6", + "stylelint": "14.16.1", + "stylelint-config-standard": "26.0.0", + "stylelint-config-standard-scss": "5.0.0", + "stylelint-junit-formatter": "0.2.2", + "typescript": "5.7.3", + "vue": "3.5.22", + "vue-eslint-parser": "9.4.3" } } diff --git a/src/Resources/app/administration/src/core/data/migration.store.js b/src/Resources/app/administration/src/core/data/migration.store.js deleted file mode 100644 index bb07eab83..000000000 --- a/src/Resources/app/administration/src/core/data/migration.store.js +++ /dev/null @@ -1,266 +0,0 @@ -const { Criteria } = Shopware.Data; - -const migrationApiService = Shopware.Service('migrationApiService'); -const repositoryFactory = Shopware.Service('repositoryFactory'); - -const migrationGeneralSettingRepository = repositoryFactory.create('swag_migration_general_setting'); - -/** - * The pinia store for handling all global data that is needed for the migration process. - * @module - * @private - * @sw-package fundamentals@after-sales - */ -export default { - namespaced: true, - - state: () => ({ - /** - * The id of the currently selected connection to a source system. - */ - connectionId: null, - - /** - * The environment information of the connection check. - */ - environmentInformation: {}, - - /** - * Date object on when the last connection check request was done. - */ - lastConnectionCheck: null, - - /** - * Flag which sets the whole module into a loading state - */ - isLoading: false, - - /** - * The possible data that the user can migrate. - */ - dataSelectionTableData: [], - - /** - * The selected data ids that the user wants to migrate. - */ - dataSelectionIds: [], - - /** - * The premapping structure, that the user must match. - */ - premapping: [], - - /** - * Flag to indicate if the user has confirmed the warning about different currencies and languages. - * Will also be set to true if there are no warnings. - */ - warningConfirmed: false, - }), - - getters: { - isPremappingValid(state) { - return !state.premapping.some((group) => { - return group.mapping.some((mapping) => { - return mapping.destinationUuid === null || mapping.destinationUuid === ''; - }); - }); - }, - - isMigrationAllowed(state) { - const tableDataIds = state.dataSelectionTableData.map((data) => { - if (data.requiredSelection === false) { - return data.id; - } - - return null; - }); - - const migrationAllowedByDataSelection = state.dataSelectionIds.some(id => tableDataIds.includes(id)); - const migrationAllowedByEnvironment = state.environmentInformation?.migrationDisabled === false; - - return migrationAllowedByDataSelection && - migrationAllowedByEnvironment && - !state.isLoading && - state.isPremappingValid && - state.warningConfirmed; - }, - }, - - actions: { - setConnectionId(id) { - this.connectionId = id; - }, - - setEnvironmentInformation(environmentInformation) { - this.environmentInformation = environmentInformation; - }, - - setLastConnectionCheck(date) { - this.lastConnectionCheck = date; - }, - - setIsLoading(isLoading) { - this.isLoading = isLoading; - }, - - setDataSelectionIds(newIds) { - this.dataSelectionIds = newIds; - }, - - setDataSelectionTableData(newTableData) { - this.dataSelectionTableData = newTableData; - }, - - // merges the existing premapping (in the state) with the newly provided one. - // resets the state premapping if an empty array is passed as an argument. - setPremapping(newPremapping) { - if (newPremapping === undefined || newPremapping === null || newPremapping.length < 1) { - this.premapping = []; - return; - } - - newPremapping.forEach((group) => { - // the premapping is grouped by entity, find the corresponding group in the state - let existingGroup = this.premapping.find( - (existingGroupItem) => existingGroupItem.entity === group.entity, - ); - - if (!existingGroup) { - // if it doesn't exist, create a new group for this entity with no mappings - existingGroup = { - choices: group.choices, - entity: group.entity, - mapping: [], - }; - // and add it to the state premapping groups - this.premapping.push(existingGroup); - } else { - // in case the group already exists, override the choices by the latest ones received from the server - existingGroup.choices = group.choices; - } - - group.mapping.forEach((mapping) => { - const existingMapping = existingGroup.mapping.find( - // sourceId is unique per entity and always provided by the backend - (existingMappingItem) => existingMappingItem.sourceId === mapping.sourceId, - ); - - if (existingMapping) { - // mapping already exist, check if it was already set and override if not - if (!existingMapping.destinationUuid) { - existingMapping.destinationUuid = mapping.destinationUuid; - } - return; - } - - const newMapping = { - ...mapping, - // build a unique identifier, which can be used as a vue key for reactivity (v-for) - id: `${existingGroup.entity}-${mapping.sourceId}`, - }; - - // either push the new mapping to the start or end - // depending on if it is already filled (automatically by the backend) - if (mapping.destinationUuid) { - existingGroup.mapping.push(newMapping); - } else { - existingGroup.mapping.unshift(newMapping); - } - }); - }); - }, - - setWarningConfirmed(confirmed) { - this.warningConfirmed = confirmed; - }, - - async init(forceFullStateReload = false) { - this.isLoading = true; - - const connectionIdChanged = await this.fetchConnectionId(); - await this.fetchEnvironmentInformation(); // Always fetch latest environment info - - if (forceFullStateReload || connectionIdChanged) { - // First, clear old user input - this.premapping = []; - this.dataSelectionIds = []; - this.warningConfirmed = false; - - // Then fetch new data - await this.fetchDataSelectionIds(); - } - - this.isLoading = false; - }, - - /** - * @returns {Promise} whether the connection id has changed to a new valid one - */ - async fetchConnectionId() { - try { - const criteria = new Criteria(1, 1); - const settings = await migrationGeneralSettingRepository.search(criteria, Shopware.Context.api); - - if (settings.length === 0) { - return false; - } - - const newConnectionId = settings.first().selectedConnectionId; - if (newConnectionId === this.connectionId) { - return false; - } - - this.connectionId = newConnectionId; - return true; - } catch (e) { - await this.createErrorNotification('swag-migration.api-error.fetchConnectionId'); - this.connectionId = null; - return false; - } - }, - - async fetchEnvironmentInformation() { - this.environmentInformation = {}; - - if (this.connectionId === null) { - return; - } - - try { - this.environmentInformation = await migrationApiService.checkConnection(this.connectionId); - this.lastConnectionCheck = new Date(); - } catch (e) { - await this.createErrorNotification('swag-migration.api-error.checkConnection'); - } - }, - - async fetchDataSelectionIds() { - this.dataSelectionTableData = []; - - if (this.connectionId === null) { - return; - } - - try { - const dataSelection = await migrationApiService.getDataSelection(this.connectionId); - this.dataSelectionTableData = dataSelection; - this.dataSelectionIds = dataSelection.filter(selection => selection.requiredSelection) - .map(selection => selection.id); - } catch (e) { - await this.createErrorNotification('swag-migration.api-error.getDataSelection'); - } - }, - - async createErrorNotification(errorMessageKey) { - await this.$patch(() => { - // Assuming notification system exists - // Replace this with how notifications are handled in your system - Shopware.State.dispatch('notification/createNotification', { - variant: 'error', - title: Shopware.Snippet.tc('global.default.error'), - message: Shopware.Snippet.tc(errorMessageKey), - }); - }); - }, - }, -}; diff --git a/src/Resources/app/administration/src/core/service/api/swag-migration.api.service.js b/src/Resources/app/administration/src/core/service/api/swag-migration.api.service.js deleted file mode 100644 index 2bb568385..000000000 --- a/src/Resources/app/administration/src/core/service/api/swag-migration.api.service.js +++ /dev/null @@ -1,245 +0,0 @@ -const ApiService = Shopware.Classes.ApiService; - -/** - * @private - * @sw-package fundamentals@after-sales - */ -export const MIGRATION_STEP = Object.freeze({ - IDLE: 'idle', - FETCHING: 'fetching', - WRITING: 'writing', - MEDIA_PROCESSING: 'media-processing', - CLEANUP: 'cleanup', - INDEXING: 'indexing', - WAITING_FOR_APPROVE: 'waiting-for-approve', - ABORTING: 'aborting', -}); - -/** - * @private - * @sw-package fundamentals@after-sales - */ -class MigrationApiService extends ApiService { - constructor(httpClient, loginService, apiEndpoint = 'migration') { - super(httpClient, loginService, apiEndpoint); - this.basicConfig = { - timeout: 30000, - version: Shopware.Context.api.apiVersion, - }; - } - - updateConnectionCredentials(connectionId, credentialFields, additionalHeaders = {}) { - const headers = this.getBasicHeaders(additionalHeaders); - - return this.httpClient.post(`_action/${this.getApiBasePath()}/update-connection-credentials`, { - connectionId, - credentialFields, - }, { - ...this.basicConfig, - headers, - }).then((response) => { - return ApiService.handleResponse(response); - }); - } - - checkConnection(connectionId, additionalHeaders = {}) { - const headers = this.getBasicHeaders(additionalHeaders); - - return this.httpClient.post(`_action/${this.getApiBasePath()}/check-connection`, { connectionId }, { - ...this.basicConfig, - headers, - }).then((response) => { - return ApiService.handleResponse(response); - }); - } - - getDataSelection(connectionId, additionalHeaders = {}) { - const headers = this.getBasicHeaders(additionalHeaders); - - return this.httpClient.get(`_action/${this.getApiBasePath()}/data-selection`, { - ...this.basicConfig, - params: { - connectionId, - }, - headers, - }).then((response) => { - return ApiService.handleResponse(response); - }); - } - - /** - * @param {string[]} dataSelectionIds - */ - generatePremapping(dataSelectionIds) { - const headers = this.getBasicHeaders(); - - return this.httpClient.post(`_action/${this.getApiBasePath()}/generate-premapping`, { dataSelectionIds }, { - ...this.basicConfig, - headers, - }).then((response) => { - return ApiService.handleResponse(response); - }); - } - - writePremapping(premapping) { - const headers = this.getBasicHeaders(); - - return this.httpClient.post(`_action/${this.getApiBasePath()}/write-premapping`, { premapping }, { - ...this.basicConfig, - headers, - }).then((response) => { - return ApiService.handleResponse(response); - }); - } - - /** - * @param {string[]} dataSelectionNames - */ - startMigration(dataSelectionNames) { - const headers = this.getBasicHeaders(); - - return this.httpClient.post(`_action/${this.getApiBasePath()}/start-migration`, { - dataSelectionNames, - }, { - ...this.basicConfig, - headers, - }).then((response) => { - return ApiService.handleResponse(response); - }); - } - - getState() { - const headers = this.getBasicHeaders(); - - return this.httpClient.get(`_action/${this.getApiBasePath()}/get-state`, { - ...this.basicConfig, - headers, - }).then((response) => { - return ApiService.handleResponse(response); - }); - } - - approveFinishedMigration() { - const headers = this.getBasicHeaders(); - - return this.httpClient.post(`_action/${this.getApiBasePath()}/approve-finished`, {}, { - ...this.basicConfig, - headers, - }).then((response) => { - return ApiService.handleResponse(response); - }); - } - - abortMigration() { - const headers = this.getBasicHeaders(); - - return this.httpClient.post(`_action/${this.getApiBasePath()}/abort-migration`, {}, { - ...this.basicConfig, - headers, - }).then((response) => { - return ApiService.handleResponse(response); - }); - } - - getProfiles() { - const headers = this.getBasicHeaders(); - - return this.httpClient.get(`_action/${this.getApiBasePath()}/get-profiles`, { - ...this.basicConfig, - headers, - }).then((response) => { - return ApiService.handleResponse(response); - }); - } - - getGateways(profileName) { - const headers = this.getBasicHeaders(); - - return this.httpClient.get(`_action/${this.getApiBasePath()}/get-gateways`, { - ...this.basicConfig, - params: { - profileName, - }, - headers, - }).then((response) => { - return ApiService.handleResponse(response); - }); - } - - getProfileInformation(profileName, gatewayName) { - const headers = this.getBasicHeaders(); - - return this.httpClient.get(`_action/${this.getApiBasePath()}/get-profile-information`, { - ...this.basicConfig, - params: { - profileName, - gatewayName, - }, - headers, - }).then((response) => { - return ApiService.handleResponse(response); - }); - } - - getGroupedLogsOfRun(runUuid) { - const headers = this.getBasicHeaders(); - - return this.httpClient.get(`${this.getApiBasePath()}/get-grouped-logs-of-run`, { - ...this.basicConfig, - params: { - runUuid, - }, - headers, - }).then((response) => { - return ApiService.handleResponse(response); - }); - } - - clearDataOfRun(runUuid) { - const headers = this.getBasicHeaders(); - - return this.httpClient.post(`_action/${this.getApiBasePath()}/clear-data-of-run`, { - runUuid, - }, { - ...this.basicConfig, - headers, - }).then((response) => { - return ApiService.handleResponse(response); - }); - } - - resetChecksums(connectionId, additionalHeaders = {}) { - const headers = this.getBasicHeaders(additionalHeaders); - - return this.httpClient.post(`_action/${this.getApiBasePath()}/reset-checksums`, { - connectionId, - }, { - ...this.basicConfig, - headers, - }).then((response) => { - return ApiService.handleResponse(response); - }); - } - - cleanupMigrationData(additionalHeaders = {}) { - const headers = this.getBasicHeaders(additionalHeaders); - return this.httpClient.post(`_action/${this.getApiBasePath()}/cleanup-migration-data`, { - ...this.basicConfig, - headers, - }); - } - - isMediaProcessing(additionalHeaders = {}) { - const headers = this.getBasicHeaders(additionalHeaders); - return this.httpClient.get(`_action/${this.getApiBasePath()}/is-media-processing`, { - ...this.basicConfig, - headers, - }); - } -} - -/** - * @private - * @sw-package fundamentals@after-sales - */ -export default MigrationApiService; diff --git a/src/Resources/app/administration/src/core/service/api/swag-migration.api.service.ts b/src/Resources/app/administration/src/core/service/api/swag-migration.api.service.ts new file mode 100644 index 000000000..749c5c24e --- /dev/null +++ b/src/Resources/app/administration/src/core/service/api/swag-migration.api.service.ts @@ -0,0 +1,605 @@ +import type { AxiosInstance, AxiosResponse, AxiosRequestConfig } from 'axios'; +import type { LoginService } from '@administration/src/core/service/login.service'; +import type { ApiResponse } from '@administration/src/core/service/api.service'; +import type { + MigrationDataSelection, + MigrationEnvironmentInformation, + MigrationGateway, + MigrationProfile, + MigrationState, + MigrationPremapping, + MigrationCredentials, + MigrationError, +} from '../../../type/types'; + +type AdditionalHeaders = Record; + +const ApiService = Shopware.Classes.ApiService; + +/** + * @private + */ +export const MIGRATION_API_SERVICE = 'migrationApiService'; + +/** + * @private + * @sw-package fundamentals@after-sales + */ +export const MIGRATION_STEP = { + IDLE: 'idle', + FETCHING: 'fetching', + ERROR_RESOLUTION: 'error-resolution', + WRITING: 'writing', + MEDIA_PROCESSING: 'media-processing', + CLEANUP: 'cleanup', + INDEXING: 'indexing', + WAITING_FOR_APPROVE: 'waiting-for-approve', + ABORTING: 'aborting', +} as const; + +/** + * @private + */ +export type LogGroup = { + code: string; + entityName: string | null; + fieldName: string | null; + count: number; +}; + +/** + * @private + */ +export type LogLevelCounts = { + error: number; + warning: number; + info: number; +}; + +/** + * @private + * @sw-package fundamentals@after-sales + */ +export default class MigrationApiService extends ApiService { + private readonly basicConfig: AxiosRequestConfig & { version: string }; + + constructor(httpClient: AxiosInstance, loginService: LoginService, apiEndpoint = 'migration') { + super(httpClient, loginService, apiEndpoint); + // @ts-ignore + this.name = MIGRATION_API_SERVICE; + this.basicConfig = { + timeout: 30000, + version: Shopware.Context.api.apiVersion, + }; + } + + async updateConnectionCredentials( + connectionId: string, + credentialFields: Record, + additionalHeaders: AdditionalHeaders = {}, + ): Promise> { + // @ts-ignore + const headers = this.getBasicHeaders(additionalHeaders); + + // @ts-ignore + return this.httpClient + .post( + // @ts-ignore + `_action/${this.getApiBasePath()}/update-connection-credentials`, + { + connectionId, + credentialFields, + }, + { + ...this.basicConfig, + headers, + }, + ) + .then((response: AxiosResponse) => { + return ApiService.handleResponse(response as AxiosResponse); + }); + } + + async checkConnection( + connectionId: string, + credentialFields?: Record, + additionalHeaders: AdditionalHeaders = {}, + ): Promise { + // @ts-ignore + const headers = this.getBasicHeaders(additionalHeaders); + + const payload: { connectionId: string; credentialFields?: Record } = { connectionId }; + + if (credentialFields) { + payload.credentialFields = credentialFields; + } + + // @ts-ignore + return this.httpClient + .post( + // @ts-ignore + `_action/${this.getApiBasePath()}/check-connection`, + payload, + { + ...this.basicConfig, + headers, + }, + ) + .then((response: AxiosResponse) => { + return ApiService.handleResponse(response); + }); + } + + async getDataSelection( + connectionId: string, + additionalHeaders: AdditionalHeaders = {}, + ): Promise { + // @ts-ignore + const headers = this.getBasicHeaders(additionalHeaders); + + return ( + // @ts-ignore + this.httpClient + // @ts-ignore + .get(`_action/${this.getApiBasePath()}/data-selection`, { + ...this.basicConfig, + params: { + connectionId, + }, + headers, + }) + .then((response: AxiosResponse) => { + return ApiService.handleResponse(response); + }) + ); + } + + async generatePremapping(dataSelectionIds: string[]): Promise { + // @ts-ignore + const headers = this.getBasicHeaders(); + + // @ts-ignore + return this.httpClient + .post( + // @ts-ignore + `_action/${this.getApiBasePath()}/generate-premapping`, + { dataSelectionIds }, + { + ...this.basicConfig, + headers, + }, + ) + .then((response: AxiosResponse) => { + return ApiService.handleResponse(response); + }); + } + + async writePremapping(premapping: MigrationPremapping[]): Promise> { + // @ts-ignore + const headers = this.getBasicHeaders(); + + // @ts-ignore + return this.httpClient + .post( + // @ts-ignore + `_action/${this.getApiBasePath()}/write-premapping`, + { premapping }, + { + ...this.basicConfig, + headers, + }, + ) + .then((response: AxiosResponse) => { + return ApiService.handleResponse(response); + }); + } + + async startMigration(dataSelectionNames: string[]): Promise> { + // @ts-ignore + const headers = this.getBasicHeaders(); + + // @ts-ignore + return this.httpClient + .post( + // @ts-ignore + `_action/${this.getApiBasePath()}/start-migration`, + { + dataSelectionNames, + }, + { + ...this.basicConfig, + headers, + }, + ) + .then((response: AxiosResponse) => { + return ApiService.handleResponse(response); + }); + } + + async getState(): Promise { + // @ts-ignore + const headers = this.getBasicHeaders(); + + return ( + // @ts-ignore + this.httpClient + // @ts-ignore + .get(`_action/${this.getApiBasePath()}/get-state`, { + ...this.basicConfig, + headers, + }) + .then((response: AxiosResponse) => { + return ApiService.handleResponse(response); + }) + ); + } + + async approveFinishedMigration(): Promise> { + // @ts-ignore + const headers = this.getBasicHeaders(); + + // @ts-ignore + return this.httpClient + .post( + // @ts-ignore + `_action/${this.getApiBasePath()}/approve-finished`, + {}, + { + ...this.basicConfig, + headers, + }, + ) + .then((response: AxiosResponse) => { + return ApiService.handleResponse(response); + }); + } + + async abortMigration(): Promise> { + // @ts-ignore + const headers = this.getBasicHeaders(); + + // @ts-ignore + return this.httpClient + .post( + // @ts-ignore + `_action/${this.getApiBasePath()}/abort-migration`, + {}, + { + ...this.basicConfig, + headers, + }, + ) + .then((response: AxiosResponse) => { + return ApiService.handleResponse(response); + }); + } + + async continueAfterErrorResolution(): Promise> { + // @ts-ignore + const headers = this.getBasicHeaders(); + + // @ts-ignore + return this.httpClient + .post( + // @ts-ignore + `_action/${this.getApiBasePath()}/resume-after-fixes`, + {}, + { + ...this.basicConfig, + headers, + }, + ) + .then((response: AxiosResponse) => { + return ApiService.handleResponse(response); + }); + } + + async getProfiles(): Promise { + // @ts-ignore + const headers = this.getBasicHeaders(); + + return ( + // @ts-ignore + this.httpClient + // @ts-ignore + .get(`_action/${this.getApiBasePath()}/get-profiles`, { + ...this.basicConfig, + headers, + }) + .then((response: AxiosResponse) => { + return ApiService.handleResponse(response); + }) + ); + } + + async getGateways(profileName: string): Promise { + // @ts-ignore + const headers = this.getBasicHeaders(); + + return ( + // @ts-ignore + this.httpClient + // @ts-ignore + .get(`_action/${this.getApiBasePath()}/get-gateways`, { + ...this.basicConfig, + params: { + profileName, + }, + headers, + }) + .then((response: AxiosResponse) => { + return ApiService.handleResponse(response); + }) + ); + } + + async getProfileInformation(profileName: string, gatewayName: string): Promise { + // @ts-ignore + const headers = this.getBasicHeaders(); + + return ( + // @ts-ignore + this.httpClient + // @ts-ignore + .get(`_action/${this.getApiBasePath()}/get-profile-information`, { + ...this.basicConfig, + params: { + profileName, + gatewayName, + }, + headers, + }) + .then((response: AxiosResponse) => { + return ApiService.handleResponse(response); + }) + ); + } + + async getGroupedLogsOfRun(runUuid: string): Promise<{ + total: number; + downloadUrl: string; + items: MigrationError[]; + }> { + // @ts-ignore + const headers = this.getBasicHeaders(); + + return ( + // @ts-ignore + this.httpClient + // @ts-ignore + .get(`_action/${this.getApiBasePath()}/get-grouped-logs-of-run`, { + ...this.basicConfig, + params: { + runUuid, + }, + headers, + }) + .then((response: AxiosResponse) => { + return ApiService.handleResponse(response); + }) + ); + } + + async clearDataOfRun(runUuid: string): Promise> { + // @ts-ignore + const headers = this.getBasicHeaders(); + + // @ts-ignore + return this.httpClient + .post( + // @ts-ignore + `_action/${this.getApiBasePath()}/clear-data-of-run`, + { + runUuid, + }, + { + ...this.basicConfig, + headers, + }, + ) + .then((response: AxiosResponse) => { + return ApiService.handleResponse(response); + }); + } + + async resetChecksums(connectionId: string, additionalHeaders: AdditionalHeaders = {}): Promise> { + // @ts-ignore + const headers = this.getBasicHeaders(additionalHeaders); + + // @ts-ignore + return this.httpClient + .post( + // @ts-ignore + `_action/${this.getApiBasePath()}/reset-checksums`, + { + connectionId, + }, + { + ...this.basicConfig, + headers, + }, + ) + .then((response: AxiosResponse) => { + return ApiService.handleResponse(response); + }); + } + + async cleanupMigrationData(additionalHeaders: AdditionalHeaders = {}): Promise> { + // @ts-ignore + const headers = this.getBasicHeaders(additionalHeaders); + + // @ts-ignore + return this.httpClient.post( + // @ts-ignore + `_action/${this.getApiBasePath()}/cleanup-migration-data`, + {}, + { + ...this.basicConfig, + headers, + }, + ); + } + + async isMediaProcessing(additionalHeaders: AdditionalHeaders = {}): Promise { + // @ts-ignore + const headers = this.getBasicHeaders(additionalHeaders); + + // @ts-ignore + return this.httpClient.get(`_action/${this.getApiBasePath()}/is-media-processing`, { + ...this.basicConfig, + headers, + }); + } + + async downloadLogsOfRun(runUuid: string, additionalHeaders: AdditionalHeaders = {}): Promise { + // @ts-ignore + const headers = this.getBasicHeaders(additionalHeaders); + + // @ts-ignore + return this.httpClient + .post( + // @ts-ignore + `_action/${this.getApiBasePath()}/download-logs-of-run`, + { runUuid }, + { + ...this.basicConfig, + headers, + responseType: 'blob', + }, + ) + .then((response: AxiosResponse) => { + return response.data; + }); + } + + async getLogGroups( + runId: string, + level: string, + page: number, + limit: number, + sortBy: string, + sortDirection: 'ASC' | 'DESC', + filter: { + code: string | null; + status: 'resolved' | 'unresolved' | null; + entity: string | null; + field: string | null; + }, + additionalHeaders: AdditionalHeaders = {}, + ): Promise<{ + total: number; + items: LogGroup[]; + levelCounts: LogLevelCounts; + }> { + // @ts-ignore + const headers = this.getBasicHeaders(additionalHeaders); + + const params: Record = { + runId, + level, + page, + limit, + sortBy, + sortDirection, + }; + + if (filter.code) { + params.filterCode = filter.code; + } + + if (filter.status) { + params.filterStatus = filter.status; + } + + if (filter.entity) { + params.filterEntity = filter.entity; + } + + if (filter.field) { + params.filterField = filter.field; + } + + return ( + // @ts-ignore + this.httpClient + // @ts-ignore + .get(`_action/${this.getApiBasePath()}/get-log-groups`, { + ...this.basicConfig, + params, + headers, + }) + .then((response: AxiosResponse) => { + return ApiService.handleResponse(response); + }) + ); + } + + async isResettingChecksums(): Promise { + // @ts-ignore + const headers = this.getBasicHeaders(); + + return ( + // @ts-ignore + this.httpClient + // @ts-ignore + .get(`_action/${this.getApiBasePath()}/is-resetting-checksums`, { + ...this.basicConfig, + headers, + }) + .then((response: AxiosResponse) => { + return ApiService.handleResponse(response); + }) + ); + } + + async isTruncatingMigrationData(): Promise { + // @ts-ignore + const headers = this.getBasicHeaders(); + + return ( + // @ts-ignore + this.httpClient + // @ts-ignore + .get(`_action/${this.getApiBasePath()}/is-truncating-migration-data`, { + ...this.basicConfig, + headers, + }) + .then((response: AxiosResponse) => { + return ApiService.handleResponse(response); + }) + ); + } + + async getAllLogIds( + runId: string, + code: string, + entityName: string, + fieldName: string, + connectionId?: string, + additionalHeaders: AdditionalHeaders = {}, + ): Promise<{ ids: string[] }> { + // @ts-ignore + const headers = this.getBasicHeaders(additionalHeaders); + + // @ts-ignore + return this.httpClient + .post( + // @ts-ignore + `_action/${this.getApiBasePath()}/get-all-log-ids`, + { + runId, + code, + entityName, + fieldName, + connectionId, + }, + { + ...this.basicConfig, + headers, + }, + ) + .then((response: AxiosResponse) => { + return ApiService.handleResponse(response); + }); + } +} diff --git a/src/Resources/app/administration/src/core/service/index.js b/src/Resources/app/administration/src/core/service/index.ts similarity index 57% rename from src/Resources/app/administration/src/core/service/index.js rename to src/Resources/app/administration/src/core/service/index.ts index 58b0732ac..c6a67dc77 100644 --- a/src/Resources/app/administration/src/core/service/index.js +++ b/src/Resources/app/administration/src/core/service/index.ts @@ -1,4 +1,4 @@ -import MigrationApiService from './api/swag-migration.api.service'; +import MigrationApiService, { MIGRATION_API_SERVICE } from './api/swag-migration.api.service'; const { Application } = Shopware; @@ -6,8 +6,7 @@ const { Application } = Shopware; * @sw-package fundamentals@after-sales * @private */ - -Application.addServiceProvider('migrationApiService', (container) => { +Application.addServiceProvider(MIGRATION_API_SERVICE, (container: ServiceContainer) => { const initContainer = Application.getContainer('init'); return new MigrationApiService(initContainer.httpClient, container.loginService); }); diff --git a/src/Resources/app/administration/src/main.ts b/src/Resources/app/administration/src/main.ts index 1494c0a7d..0a509ed85 100644 --- a/src/Resources/app/administration/src/main.ts +++ b/src/Resources/app/administration/src/main.ts @@ -2,8 +2,7 @@ * @sw-package fundamentals@after-sales * @private */ - +import './type/global.types'; +import './init/translation.init'; import './core/service'; import './module/swag-migration'; - -import './init/translation.init'; diff --git a/src/Resources/app/administration/src/module/swag-migration/acl/index.ts b/src/Resources/app/administration/src/module/swag-migration/acl/index.ts new file mode 100644 index 000000000..971f38cd6 --- /dev/null +++ b/src/Resources/app/administration/src/module/swag-migration/acl/index.ts @@ -0,0 +1,81 @@ +const MIGRATION_ACL_KEY = 'swag_migration'; + +const acl = { + category: 'permissions', + parent: 'settings', + key: MIGRATION_ACL_KEY, + roles: { + viewer: { + privileges: [ + 'swag_migration_connection:read', + 'swag_migration_data:read', + 'swag_migration_fix:read', + 'swag_migration_general_setting:read', + 'swag_migration_logging:read', + 'swag_migration_mapping:read', + 'swag_migration_media_file:read', + 'swag_migration_run:read', + 'swag_migration_history:read', + 'system_config:read', + ], + dependencies: [], + }, + editor: { + privileges: [ + 'swag_migration_connection:update', + 'swag_migration_data:update', + 'swag_migration_fix:update', + 'swag_migration_general_setting:update', + 'swag_migration_logging:update', + 'swag_migration_mapping:update', + 'swag_migration_media_file:update', + 'swag_migration_run:update', + 'swag_migration_history:update', + ], + dependencies: [ + 'swag_migration.viewer', + ], + }, + creator: { + privileges: [ + 'swag_migration_connection:create', + 'swag_migration_data:create', + 'swag_migration_fix:create', + 'swag_migration_general_setting:create', + 'swag_migration_logging:create', + 'swag_migration_mapping:create', + 'swag_migration_media_file:create', + 'swag_migration_run:create', + 'swag_migration_history:create', + ], + dependencies: [ + 'swag_migration.viewer', + 'swag_migration.editor', + ], + }, + deleter: { + privileges: [ + 'swag_migration_connection:delete', + 'swag_migration_data:delete', + 'swag_migration_fix:delete', + 'swag_migration_general_setting:delete', + 'swag_migration_logging:delete', + 'swag_migration_mapping:delete', + 'swag_migration_media_file:delete', + 'swag_migration_run:delete', + 'swag_migration_history:delete', + ], + dependencies: [ + 'swag_migration.viewer', + ], + }, + }, +}; + +Shopware.Service('privileges').addPrivilegeMappingEntry(acl); + +/** + * @private + * @sw-package fundamentals@after-sales + */ +export { MIGRATION_ACL_KEY, acl }; diff --git a/src/Resources/app/administration/src/module/swag-migration/component/card/index.js b/src/Resources/app/administration/src/module/swag-migration/component/card/index.js deleted file mode 100644 index 21dbe0f7a..000000000 --- a/src/Resources/app/administration/src/module/swag-migration/component/card/index.js +++ /dev/null @@ -1,10 +0,0 @@ -/** - * @sw-package fundamentals@after-sales - * @private - */ - -import './swag-migration-shop-information'; -import './swag-migration-premapping'; -import './swag-migration-progress-bar'; -import './swag-migration-assistant'; -import './swag-migration-confirm-warning'; diff --git a/src/Resources/app/administration/src/module/swag-migration/component/card/index.ts b/src/Resources/app/administration/src/module/swag-migration/component/card/index.ts new file mode 100644 index 000000000..a5b3dbc90 --- /dev/null +++ b/src/Resources/app/administration/src/module/swag-migration/component/card/index.ts @@ -0,0 +1,8 @@ +/** + * @sw-package fundamentals@after-sales + * @private + */ +Shopware.Component.register('swag-migration-shop-information', () => import('./swag-migration-shop-information')); +Shopware.Component.register('swag-migration-premapping', () => import('./swag-migration-premapping')); +Shopware.Component.register('swag-migration-progress-bar', () => import('./swag-migration-progress-bar')); +Shopware.Component.register('swag-migration-confirm-warning', () => import('./swag-migration-confirm-warning')); diff --git a/src/Resources/app/administration/src/module/swag-migration/component/card/swag-migration-assistant/index.js b/src/Resources/app/administration/src/module/swag-migration/component/card/swag-migration-assistant/index.js deleted file mode 100644 index f13ba7c50..000000000 --- a/src/Resources/app/administration/src/module/swag-migration/component/card/swag-migration-assistant/index.js +++ /dev/null @@ -1,18 +0,0 @@ -import template from './swag-migration-assistant.html.twig'; -import './swag-migration-assistant.scss'; - -const { Component } = Shopware; - -/** - * @private - * @sw-package fundamentals@after-sales - */ -Component.register('swag-migration-assistant', { - computed: { - assetFilter() { - return Shopware.Filter.getByName('asset'); - }, - }, - - template, -}); diff --git a/src/Resources/app/administration/src/module/swag-migration/component/card/swag-migration-assistant/swag-migration-assistant.html.twig b/src/Resources/app/administration/src/module/swag-migration/component/card/swag-migration-assistant/swag-migration-assistant.html.twig deleted file mode 100644 index 4e627c403..000000000 --- a/src/Resources/app/administration/src/module/swag-migration/component/card/swag-migration-assistant/swag-migration-assistant.html.twig +++ /dev/null @@ -1,102 +0,0 @@ -{% block swag_migration_assistant %} - - - {% block swag_migration_assistant_headline %} -

- {{ $tc('swag-migration.index.assistantCard.headline') }} -

- {% endblock %} - - {% block swag_migration_assistant_connection %} -
- - {% block swag_migration_assistant_connection_illustration %} - - {% endblock %} - - {% block swag_migration_assistant_connection_title %} -
- {{ $tc('swag-migration.index.assistantCard.connection.title') }} -
- {% endblock %} - - {% block swag_migration_assistant_connection_content %} -

- {{ $tc('swag-migration.index.assistantCard.connection.content') }} -

- {% endblock %} - - {% block swag_migration_assistant_connection_content_link %} - - {% endblock %} -
- {% endblock %} - - {% block swag_migration_assistant_dataSelection %} -
- - {% block swag_migration_assistant_dataSelection_illustration %} - - {% endblock %} - - {% block swag_migration_assistant_dataSelection_title %} -
- {{ $tc('swag-migration.index.assistantCard.dataSelection.title') }} -
- {% endblock %} - - {% block swag_migration_assistant_dataSelection_content %} -

- {{ $tc('swag-migration.index.assistantCard.dataSelection.content') }} -

- {% endblock %} -
- {% endblock %} - - {% block swag_migration_assistant_migrationOverview %} -
- - {% block swag_migration_assistant_migrationOverview_illustration %} - - {% endblock %} - - {% block swag_migration_assistant_migrationOverview_title %} -
- {{ $tc('swag-migration.index.assistantCard.migrationOverview.title') }} -
- {% endblock %} - - {% block swag_migration_assistant_migrationOverview_content %} -

- {{ $tc('swag-migration.index.assistantCard.migrationOverview.content') }} -

- {% endblock %} -
- {% endblock %} - - {% block swag_migration_assistant_finish %} -
- - {% block swag_migration_assistant_finish_title %} -
- {{ $tc('swag-migration.index.assistantCard.finish') }} -
- {% endblock %} -
- {% endblock %} -
-{% endblock %} diff --git a/src/Resources/app/administration/src/module/swag-migration/component/card/swag-migration-assistant/swag-migration-assistant.scss b/src/Resources/app/administration/src/module/swag-migration/component/card/swag-migration-assistant/swag-migration-assistant.scss deleted file mode 100644 index 916e760c0..000000000 --- a/src/Resources/app/administration/src/module/swag-migration/component/card/swag-migration-assistant/swag-migration-assistant.scss +++ /dev/null @@ -1,46 +0,0 @@ -@import "~scss/variables"; - -.swag-migration-assistant { - h4.swag-migration-assistant__headline { - font-size: 32px; - text-align: center; - margin: 0; - padding-top: var(--scale-size-10); - } - - .swag-migration-assistant__paragraph { - text-align: center; - width: 80%; - margin: var(--scale-size-80) auto 0 auto; - - &:first-of-type { - margin-top: var(--scale-size-64); - } - - &:last-of-type { - margin-top: var(--scale-size-40); - } - } - - .swag-migration-assistant__illustration { - width: 136px; - display: block; - margin: 0 auto; - padding-bottom: var(--scale-size-16); - } - - h5.swag-migration-assistant__title { - font-weight: 600; - margin-bottom: var(--scale-size-8); - } - - .swag-migration-assistant__content { - white-space: pre-line; - } - - .swag-migration-assistant__content, - .swag-migration-assistant__link a.link { - font-size: $font-size-xxs; - line-height: 22px; - } -} diff --git a/src/Resources/app/administration/src/module/swag-migration/component/card/swag-migration-confirm-warning/index.js b/src/Resources/app/administration/src/module/swag-migration/component/card/swag-migration-confirm-warning/index.js deleted file mode 100644 index e42ab3ece..000000000 --- a/src/Resources/app/administration/src/module/swag-migration/component/card/swag-migration-confirm-warning/index.js +++ /dev/null @@ -1,69 +0,0 @@ -import template from './swag-migration-confirm-warning.html.twig'; -import './swag-migration-confirm-warning.scss'; - -const { Component, Store } = Shopware; -const { mapState } = Shopware.Component.getComponentHelper(); - -/** - * @private - * @sw-package fundamentals@after-sales - */ -Component.register('swag-migration-confirm-warning', { - template, - - data() { - return { - isCurrencyChecked: false, - isLanguageChecked: false, - }; - }, - - computed: { - ...mapState(() => Store.get('swagMigration'), [ - 'environmentInformation', - ]), - - hasDifferentCurrency() { - return this.sourceSystemCurrency !== this.targetSystemCurrency; - }, - - sourceSystemCurrency() { - return this.environmentInformation.sourceSystemCurrency; - }, - - targetSystemCurrency() { - return this.environmentInformation.targetSystemCurrency; - }, - - hasDifferentLanguage() { - return this.sourceSystemLanguage !== this.targetSystemLanguage; - }, - - sourceSystemLanguage() { - return this.environmentInformation.sourceSystemLocale; - }, - - targetSystemLanguage() { - return this.environmentInformation.targetSystemLocale; - }, - - isContinuable() { - return (!this.hasDifferentCurrency || this.isCurrencyChecked) && - (!this.hasDifferentLanguage || this.isLanguageChecked); - }, - }, - - created() { - this.createdComponent(); - }, - - methods: { - createdComponent() { - this.onCheckboxValueChanged(); - }, - - onCheckboxValueChanged() { - Store.get('swagMigration').setWarningConfirmed(this.isContinuable); - }, - }, -}); diff --git a/src/Resources/app/administration/src/module/swag-migration/component/card/swag-migration-confirm-warning/index.ts b/src/Resources/app/administration/src/module/swag-migration/component/card/swag-migration-confirm-warning/index.ts new file mode 100644 index 000000000..0a2e6553f --- /dev/null +++ b/src/Resources/app/administration/src/module/swag-migration/component/card/swag-migration-confirm-warning/index.ts @@ -0,0 +1,40 @@ +import template from './swag-migration-confirm-warning.html.twig'; +import './swag-migration-confirm-warning.scss'; +import { MIGRATION_STORE_ID } from '../../../store/migration.store'; + +const { mapState } = Shopware.Component.getComponentHelper(); + +/** + * @private + * @sw-package fundamentals@after-sales + */ +export default Shopware.Component.wrapComponentConfig({ + template, + + computed: { + sourceSystemCurrency() { + return this.environmentInformation.sourceSystemCurrency; + }, + + targetSystemCurrency() { + return this.environmentInformation.targetSystemCurrency; + }, + + sourceSystemLanguage() { + return this.environmentInformation.sourceSystemLocale; + }, + + targetSystemLanguage() { + return this.environmentInformation.targetSystemLocale; + }, + + ...mapState( + () => Shopware.Store.get(MIGRATION_STORE_ID), + [ + 'environmentInformation', + 'hasCurrencyMismatch', + 'hasLanguageMismatch', + ], + ), + }, +}); diff --git a/src/Resources/app/administration/src/module/swag-migration/component/card/swag-migration-confirm-warning/swag-migration-confirm-warning.html.twig b/src/Resources/app/administration/src/module/swag-migration/component/card/swag-migration-confirm-warning/swag-migration-confirm-warning.html.twig index 1c378f3eb..248b60920 100644 --- a/src/Resources/app/administration/src/module/swag-migration/component/card/swag-migration-confirm-warning/swag-migration-confirm-warning.html.twig +++ b/src/Resources/app/administration/src/module/swag-migration/component/card/swag-migration-confirm-warning/swag-migration-confirm-warning.html.twig @@ -1,108 +1,21 @@ {% block swag_migration_confirm_warning %}
- - {% block swag_migration_confirm_warning_card %} - - - {% block swag_migration_confirm_warning_bubble %} -
- -
- {% endblock %} - - {% block swag_migration_confirm_warning_title %} -
- {{ $tc('swag-migration.index.confirmWarningCard.currencyMismatch.title') }} -
- {% endblock %} - - {% block swag_migration_confirm_warning_text %} -

- {{ $tc('swag-migration.index.confirmWarningCard.currencyMismatch.text', { sourceSystemCurrency, targetSystemCurrency }, 0) }} -

- {% endblock %} - - {% block swag_migration_confirm_warning_alert %} - - {{ $tc('swag-migration.index.confirmWarningCard.currencyMismatch.info') }} - - {% endblock %} - - {% block swag_migration_confirm_warning_question %} -

- {{ $tc('swag-migration.index.confirmWarningCard.currencyMismatch.question', { targetSystemCurrency }, 0) }} -

- {% endblock %} - - {% block swag_migration_confirm_warning_checkbox %} - - {% endblock %} -
- {% endblock %} - - {% block swag_migration_confirm_language_warning_card %} - - - {% block swag_migration_confirm_language_warning_bubble %} -
- -
- {% endblock %} - - {% block swag_migration_confirm_language_warning_title %} -
- {{ $tc('swag-migration.index.confirmWarningCard.languageMismatch.title') }} -
- {% endblock %} - - {% block swag_migration_confirm_language_warning_text %} -

- {{ $tc('swag-migration.index.confirmWarningCard.languageMismatch.text', { sourceSystemLanguage, targetSystemLanguage }, 0) }} -

- {% endblock %} - - {% block swag_migration_confirm_language_warning_alert %} - - {{ $tc('swag-migration.index.confirmWarningCard.languageMismatch.info') }} - - {% endblock %} - - {% block swag_migration_confirm_language_warning_question %} -

- {{ $tc('swag-migration.index.confirmWarningCard.languageMismatch.question', { targetSystemLanguage }, 0) }} -

- {% endblock %} - - {% block swag_migration_confirm_language_warning_checkbox %} - - {% endblock %} -
- {% endblock %} + + {{ $tc('swag-migration.index.confirmWarningCard.currencyMismatch.text', { sourceSystemCurrency, targetSystemCurrency }, 0) }} + + + + {{ $tc('swag-migration.index.confirmWarningCard.languageMismatch.text', { sourceSystemLanguage, targetSystemLanguage }, 0) }} +
{% endblock %} diff --git a/src/Resources/app/administration/src/module/swag-migration/component/card/swag-migration-confirm-warning/swag-migration-confirm-warning.scss b/src/Resources/app/administration/src/module/swag-migration/component/card/swag-migration-confirm-warning/swag-migration-confirm-warning.scss index 55a1b5b9e..828a0bd27 100644 --- a/src/Resources/app/administration/src/module/swag-migration/component/card/swag-migration-confirm-warning/swag-migration-confirm-warning.scss +++ b/src/Resources/app/administration/src/module/swag-migration/component/card/swag-migration-confirm-warning/swag-migration-confirm-warning.scss @@ -1,57 +1,10 @@ @import "~scss/variables"; .swag-migration-confirm-warning { - .swag-migration-confirm-warning__card { - text-align: center; - font-size: 14px; - } - - .swag-migration-confirm-warning__bubble { - margin: var(--scale-size-12) auto var(--scale-size-20) auto; - width: var(--scale-size-72); - height: var(--scale-size-72); - border-radius: var(--border-radius-round); - background-color: $color-pumpkin-spice-50; - flex-shrink: 0; - display: flex; - align-items: center; - justify-content: center; - } - - .swag-migration-confirm-warning__bubble-icon { - color: $color-pumpkin-spice-500; - } - - h5.swag-migration-confirm-warning__title { - font-size: 18px; - font-weight: 600; - line-height: 25px; - } - - .swag-migration-confirm-warning__alert { - text-align: center; - display: inline-flex; - } - - .swag-migration-confirm-warning__text { - padding-bottom: var(--scale-size-24); - } - - .swag-migration-confirm-warning__question { - font-weight: 600; - padding-bottom: var(--scale-size-32); - } - - .swag-migration-confirm-warning__checkbox .mt-field--checkbox__content { - display: flex; - justify-content: center; - - .mt-field { - width: auto; - } + max-width: 60rem; + margin: 0 auto; - .mt-field__label label { - flex-grow: 0; - } + .swag-migration-confirm-warning__banner { + margin: 0 auto var(--scale-size-40); } } diff --git a/src/Resources/app/administration/src/module/swag-migration/component/card/swag-migration-premapping/index.js b/src/Resources/app/administration/src/module/swag-migration/component/card/swag-migration-premapping/index.js deleted file mode 100644 index aa1cc9f82..000000000 --- a/src/Resources/app/administration/src/module/swag-migration/component/card/swag-migration-premapping/index.js +++ /dev/null @@ -1,84 +0,0 @@ -import template from './swag-migration-premapping.html.twig'; -import './swag-migration-premapping.scss'; - -const { Component, Store } = Shopware; -const { mapState } = Shopware.Component.getComponentHelper(); -const { debounce } = Shopware.Utils; - -/** - * @private - * @sw-package fundamentals@after-sales - */ -Component.register('swag-migration-premapping', { - template, - - inject: { - /** @var {MigrationApiService} migrationApiService */ - migrationApiService: 'migrationApiService', - }, - - data() { - return { - isLoading: false, - premappingInput: [], - }; - }, - - computed: { - ...mapState(() => Store.get('swagMigration'), [ - 'premapping', - 'dataSelectionIds', - 'isPremappingValid', - ]), - }, - - watch: { - dataSelectionIds() { - this.fetchPremapping(); - }, - }, - - methods: { - fetchPremapping() { - Store.get('swagMigration').setIsLoading(true); - this.isLoading = true; - - return this.migrationApiService.generatePremapping(this.dataSelectionIds) - .then((premapping) => { - Store.get('swagMigration').setPremapping(premapping); - return this.savePremapping(); - }).finally(() => { - Store.get('swagMigration').setIsLoading(false); - this.isLoading = false; - }); - }, - - async savePremapping() { - if (!this.premapping || this.premapping.length === 0) { - return; - } - - const filledOut = this.premapping.every( - (group) => group.mapping.every( - (mapping) => mapping.destinationUuid !== null && - mapping.destinationUuid !== undefined && - mapping.destinationUuid !== '', - ), - ); - - if (!filledOut) { - return; - } - - await this.migrationApiService.writePremapping(this.premapping); - }, - - onPremappingChanged() { - Store.get('swagMigration').setIsLoading(true); - debounce(async () => { - await this.savePremapping(); - Store.get('swagMigration').setIsLoading(false); - }, 500)(); - }, - }, -}); diff --git a/src/Resources/app/administration/src/module/swag-migration/component/card/swag-migration-premapping/index.ts b/src/Resources/app/administration/src/module/swag-migration/component/card/swag-migration-premapping/index.ts new file mode 100644 index 000000000..e4c3854e4 --- /dev/null +++ b/src/Resources/app/administration/src/module/swag-migration/component/card/swag-migration-premapping/index.ts @@ -0,0 +1,101 @@ +import template from './swag-migration-premapping.html.twig'; +import './swag-migration-premapping.scss'; +import type { MigrationPremapping } from '../../../../../type/types'; +import { MIGRATION_API_SERVICE } from '../../../../../core/service/api/swag-migration.api.service'; +import type { MigrationStore } from '../../../store/migration.store'; +import { MIGRATION_STORE_ID } from '../../../store/migration.store'; + +const { Store } = Shopware; +const { mapState } = Shopware.Component.getComponentHelper(); +const { debounce } = Shopware.Utils; + +/** + * @private + */ +export interface SwagMigrationPremappingData { + isLoading: boolean; + migrationStore: MigrationStore; +} + +/** + * @private + * @sw-package fundamentals@after-sales + */ +export default Shopware.Component.wrapComponentConfig({ + template, + + inject: [ + MIGRATION_API_SERVICE, + ], + + data(): SwagMigrationPremappingData { + return { + isLoading: false, + migrationStore: Store.get(MIGRATION_STORE_ID), + }; + }, + + computed: { + ...mapState( + () => Store.get(MIGRATION_STORE_ID), + [ + 'premapping', + 'dataSelectionIds', + ], + ), + }, + + watch: { + dataSelectionIds() { + this.fetchPremapping(); + }, + }, + + methods: { + fetchPremapping() { + this.migrationStore.setIsLoading(true); + this.isLoading = true; + + this.migrationApiService + .generatePremapping(this.dataSelectionIds) + .then(async (premapping: MigrationPremapping[]) => { + this.migrationStore.setPremapping(premapping); + await this.savePremapping(); + }) + .finally(() => { + this.migrationStore.setIsLoading(false); + this.isLoading = false; + }); + }, + + async savePremapping() { + if (!this.premapping || this.premapping.length === 0) { + return; + } + + const filledOut = this.premapping.every((group: MigrationPremapping) => + group.mapping.every( + (mapping) => + mapping.destinationUuid !== null && + mapping.destinationUuid !== undefined && + mapping.destinationUuid !== '', + ), + ); + + if (!filledOut) { + return; + } + + await this.migrationApiService.writePremapping(this.premapping); + }, + + async onPremappingChanged() { + this.migrationStore.setIsLoading(true); + + debounce(async () => { + await this.savePremapping(); + this.migrationStore.setIsLoading(false); + }, 500)(); + }, + }, +}); diff --git a/src/Resources/app/administration/src/module/swag-migration/component/card/swag-migration-premapping/swag-migration-premapping.html.twig b/src/Resources/app/administration/src/module/swag-migration/component/card/swag-migration-premapping/swag-migration-premapping.html.twig index 1a32ff1cb..491069bfd 100644 --- a/src/Resources/app/administration/src/module/swag-migration/component/card/swag-migration-premapping/swag-migration-premapping.html.twig +++ b/src/Resources/app/administration/src/module/swag-migration/component/card/swag-migration-premapping/swag-migration-premapping.html.twig @@ -1,63 +1,5 @@ {% block swag_migration_premapping %}
- - {% block swag_migration_premapping_unfilled_card %} - - - {% block swag_migration_premapping_unfilled_title %} -
- {{ $tc('swag-migration.index.premappingCard.unfilledTitle') }} -
- {% endblock %} - - {% block swag_migration_premapping_unfilled_caption %} -
- {{ $tc('swag-migration.index.premappingCard.unfilledCaption') }} -
- {% endblock %} - - {% block swag_migration_premapping_unfilled_alert %} - - {{ $tc('swag-migration.index.premappingCard.unfilledAlert') }} - - {% endblock %} -
- {% endblock %} - - {% block swag_migration_premapping_success_card %} - - - {% block swag_migration_premapping_success_bubble %} -
- -
- {% endblock %} - - {% block swag_migration_premapping_success_title %} -
- {{ $tc('swag-migration.index.premappingCard.validTitle') }} -
- {% endblock %} - - {% block swag_migration_premapping_success_caption %} -
- {{ $tc('swag-migration.index.premappingCard.validCaption') }} -
- {% endblock %} -
- {% endblock %} - {% block swag_migration_premapping_unfilled_mapping %} {% endblock %} - - -
- - {% block swag_migration_premapping_loader %} - - {% endblock %} - - {% block swag_migration_premapping_loading_title %} -
- {{ $tc('swag-migration.index.premappingCard.loadingTitle') }} -
- {% endblock %} - - {% block swag_migration_premapping_loading_caption %} -
- {{ $tc('swag-migration.index.premappingCard.loadingCaption') }} -
- {% endblock %} -
-
{% endblock %} diff --git a/src/Resources/app/administration/src/module/swag-migration/component/card/swag-migration-premapping/swag-migration-premapping.scss b/src/Resources/app/administration/src/module/swag-migration/component/card/swag-migration-premapping/swag-migration-premapping.scss index 95422f5c1..a59e1503e 100644 --- a/src/Resources/app/administration/src/module/swag-migration/component/card/swag-migration-premapping/swag-migration-premapping.scss +++ b/src/Resources/app/administration/src/module/swag-migration/component/card/swag-migration-premapping/swag-migration-premapping.scss @@ -1,57 +1,9 @@ @import "~scss/variables"; .swag-migration-premapping { - .swag-migration-premapping__success-card { - text-align: center; - font-size: 14px; - } - - .swag-migration-premapping__success-bubble { - margin: var(--scale-size-12) auto var(--scale-size-20) auto; - width: var(--scale-size-72); - height: var(--scale-size-72); - border-radius: var(--border-radius-round); - background-color: $color-emerald-50; - flex-shrink: 0; - display: flex; - align-items: center; - justify-content: center; - } - - .swag-migration-premapping__success-icon { - color: $color-emerald-500; - } - - .swag-migration-premapping__success-title { - font-size: 18px; - font-weight: 600; - margin-bottom: 5px; - } - - .swag-migration-premapping__success-caption { - color: $color-gray-500; - margin-bottom: 45px; - } - - .swag-migration-premapping__loading-card { - text-align: center; - font-size: 14px; - } - - .swag-migration-premapping__loading-title { - font-size: 18px; - font-weight: 600; - margin-bottom: 5px; - } - - .swag-migration-premapping__loading-caption { - color: $color-gray-500; - margin-bottom: 45px; - } - .sw-loader.swag-migration-premapping__loader { position: relative; - margin: var(--scale-size-12) auto 42px auto; + margin: var(--scale-size-12) auto var(--scale-size-40) auto; .sw-loader__container { transform: translate(-50%); @@ -59,12 +11,12 @@ } .swag-migration-premapping__alert { - max-width: 800px; + max-width: 60rem; margin-left: auto; margin-right: auto; - @media screen and (max-width: 1360px) { - max-width: 770px; + @media screen and (max-width: 85rem) { + max-width: calc(var(--scale-size-256) * 3); } } @@ -72,33 +24,15 @@ margin-top: var(--scale-size-40); } - .swag-migration-premapping__unfilled-card { - margin-top: var(--scale-size-40); - text-align: center; - font-size: 14px; - } - - .swag-migration-premapping__unfilled-title { - font-size: 18px; - font-weight: 600; - margin-top: var(--scale-size-10); - margin-bottom: 5px; - } - - .swag-migration-premapping__unfilled-caption { - color: $color-gray-500; - margin-bottom: var(--scale-size-10); - } - .swag-migration-premapping__tab-card { - font-size: 14px; + font-size: var(--font-size-xs); } .swag-migration-premapping__tab-card-item { - font-size: 14px; + font-size: var(--font-size-xs); } .sw-grid__cell-label { - font-size: 14px; + font-size: var(--font-size-xs); } -} \ No newline at end of file +} diff --git a/src/Resources/app/administration/src/module/swag-migration/component/card/swag-migration-progress-bar/index.js b/src/Resources/app/administration/src/module/swag-migration/component/card/swag-migration-progress-bar/index.ts similarity index 93% rename from src/Resources/app/administration/src/module/swag-migration/component/card/swag-migration-progress-bar/index.js rename to src/Resources/app/administration/src/module/swag-migration/component/card/swag-migration-progress-bar/index.ts index 0a9973765..14f0fe179 100644 --- a/src/Resources/app/administration/src/module/swag-migration/component/card/swag-migration-progress-bar/index.js +++ b/src/Resources/app/administration/src/module/swag-migration/component/card/swag-migration-progress-bar/index.ts @@ -1,13 +1,11 @@ import template from './swag-migration-progress-bar.html.twig'; import './swag-migration-progress-bar.scss'; -const { Component } = Shopware; - /** * @private * @sw-package fundamentals@after-sales */ -Component.register('swag-migration-progress-bar', { +export default Shopware.Component.wrapComponentConfig({ template, props: { diff --git a/src/Resources/app/administration/src/module/swag-migration/component/card/swag-migration-progress-bar/swag-migration-progress-bar.html.twig b/src/Resources/app/administration/src/module/swag-migration/component/card/swag-migration-progress-bar/swag-migration-progress-bar.html.twig index 96dcd2448..462449164 100644 --- a/src/Resources/app/administration/src/module/swag-migration/component/card/swag-migration-progress-bar/swag-migration-progress-bar.html.twig +++ b/src/Resources/app/administration/src/module/swag-migration/component/card/swag-migration-progress-bar/swag-migration-progress-bar.html.twig @@ -1,6 +1,5 @@ {% block swag_migration_progress_bar %}
- {% block swag_migration_progress_bar_heading %}
{{ title }} @@ -9,10 +8,8 @@ {% block swag_migration_progress_bar %}
- {% block swag_migration_progress_bar_left_point %}
- {% block swag_migration_progress_bar_left_bubble %}
- {% block swag_migration_progress_bar_progress_bar %} - {% block swag_migration_progress_bar_right_bubble %}
Store.get('swagMigration'), [ - 'connectionId', - 'environmentInformation', - 'lastConnectionCheck', - 'adminLocaleLanguage', - 'adminLocaleRegion', - ]), - - displayEnvironmentInformation() { - return this.environmentInformation === null ? {} : - this.environmentInformation; - }, - - migrationRunRepository() { - return this.repositoryFactory.create('swag_migration_run'); - }, - - migrationConnectionRepository() { - return this.repositoryFactory.create('swag_migration_connection'); - }, - - connectionName() { - return this.connection !== null ? - this.connection.name : - this.$tc('swag-migration.index.shopInfoCard.noConnection'); - }, - - shopUrl() { - return this.displayEnvironmentInformation.sourceSystemDomain === undefined ? '' : - this.displayEnvironmentInformation.sourceSystemDomain.replace(/^\s*https?:\/\//, ''); - }, - - shopUrlPrefix() { - if (this.displayEnvironmentInformation.sourceSystemDomain === undefined) { - return ''; - } - - const match = this.displayEnvironmentInformation.sourceSystemDomain.match(/^\s*https?:\/\//); - if (match === null) { - return ''; - } - - return match[0]; - }, - - sslActive() { - return (this.shopUrlPrefix === 'https://'); - }, - - shopUrlPrefixClass() { - return this.sslActive ? 'swag-migration-shop-information__shop-domain-prefix--is-ssl' : ''; - }, - - connectionBadgeLabel() { - if (this.serverUnreachable) { - return 'swag-migration.index.shopInfoCard.serverUnreachable'; - } - - if (this.connected) { - return 'swag-migration.index.shopInfoCard.connected'; - } - - return 'swag-migration.index.shopInfoCard.notConnected'; - }, - - connectionBadgeVariant() { - if (this.connected) { - return BADGE_TYPE.SUCCESS; - } - - return BADGE_TYPE.DANGER; - }, - - shopFirstLetter() { - return this.displayEnvironmentInformation.sourceSystemName === undefined ? 'S' : - this.displayEnvironmentInformation.sourceSystemName[0]; - }, - - profile() { - return this.connection === null || this.connection.profile === undefined ? '' : - // eslint-disable-next-line max-len - `${this.connection.profile.sourceSystemName} ${this.connection.profile.version} - ${this.connection.profile.author}`; - }, - - profileIcon() { - return this.connection === null || - this.connection.profile === undefined || - this.connection.profile.icon === undefined ? null : this.connection.profile.icon; - }, - - gateway() { - return this.connection === null || this.connection.gateway === undefined ? '' : - this.connection.gateway.snippet; - }, - - formattedLastConnectionCheckDate() { - return format.date(this.lastConnectionCheck); - }, - - formattedLastMigrationDateTime() { - return format.date(this.lastMigrationDate); - }, - - assetFilter() { - return Shopware.Filter.getByName('asset'); - }, - - showMoreInformation() { - return this.connection !== null && this.connection !== undefined; - }, - }, - - watch: { - $route: { - immediate: true, - handler() { - this.showResetMigrationConfirmModal = this.$route.meta.resetMigration; - }, - }, - - connectionId: { - immediate: true, - /** - * @param {string} newConnectionId - */ - handler(newConnectionId) { - this.fetchConnection(newConnectionId); - }, - }, - }, - - created() { - this.createdComponent(); - }, - - methods: { - createdComponent() { - this.updateLastMigrationDate(); - }, - - openResetMigrationModal() { - this.showResetMigrationConfirmModal = true; - this.$router.push({ - name: 'swag.migration.index.resetMigration', - }); - }, - - onCloseResetModal() { - this.showResetMigrationConfirmModal = false; - this.$router.push({ - name: 'swag.migration.index.main', - }); - }, - - updateLastMigrationDate() { - const criteria = new Criteria(1, 1); - criteria.addSorting(Criteria.sort('createdAt', 'DESC')); - - return this.migrationRunRepository.search(criteria, this.context).then((runs) => { - if (runs.length > 0) { - this.lastMigrationDate = runs.first().createdAt; - } else { - this.lastMigrationDate = '-'; - } - }); - }, - - /** - * @param {string} connectionId - */ - fetchConnection(connectionId) { - if (!connectionId) { - return Promise.resolve(); - } - - return this.migrationConnectionRepository.get(connectionId, this.context) - .then((connection) => { - if (!connection) { - return Promise.resolve(null); - } - delete connection.credentialFields; - this.connection = connection; - - return this.migrationApiService.getProfileInformation( - connection.profileName, - connection.gatewayName, - ); - }).then((profileInformation) => { - if (!profileInformation) { - return; - } - - this.connection.profile = profileInformation.profile; - this.connection.gateway = profileInformation.gateway; - }); - }, - - onClickEditConnectionCredentials() { - this.$router.push({ - name: 'swag.migration.wizard.credentials', - params: { - connectionId: this.connectionId, - }, - }); - }, - - onClickCreateConnection() { - this.$router.push({ - name: 'swag.migration.wizard.connectionCreate', - }); - }, - - onClickCreateInitialConnection() { - this.$router.push({ - name: 'swag.migration.wizard.introduction', - }); - }, - - onClickSelectConnection() { - this.$router.push({ - name: 'swag.migration.wizard.connectionSelect', - }); - }, - - onClickProfileInstallation() { - this.$router.push({ - name: 'swag.migration.wizard.profileInstallation', - }); - }, - - onClickRemoveConnectionCredentials() { - this.confirmModalIsLoading = true; - return this.migrationApiService.updateConnectionCredentials( - this.connectionId, - { }, - ).then(() => { - this.$router.go(); // Refresh the page - }); - }, - - onClickResetChecksums() { - this.confirmModalIsLoading = true; - return this.migrationApiService.resetChecksums(this.connectionId).then(() => { - this.showResetChecksumsConfirmModal = false; - this.confirmModalIsLoading = false; - }); - }, - - onClickResetMigration() { - this.confirmModalIsLoading = true; - return this.migrationApiService.cleanupMigrationData().then(() => { - this.showResetMigrationConfirmModal = false; - this.confirmModalIsLoading = false; - - this.$nextTick(() => { - this.$router.go(); // reload page - }); - }).catch(() => { - this.showResetMigrationConfirmModal = false; - this.confirmModalIsLoading = false; - - this.createNotificationError({ - title: this.$t( - 'swag-migration.index.shopInfoCard.resetMigrationConfirmDialog.errorNotification.title', - ), - message: this.$t( - 'swag-migration.index.shopInfoCard.resetMigrationConfirmDialog.errorNotification.message', - ), - variant: 'error', - growl: true, - }); - }); - }, - - onClickRefreshConnection() { - return Store.get('swagMigration').init(true); - }, - }, -}); diff --git a/src/Resources/app/administration/src/module/swag-migration/component/card/swag-migration-shop-information/index.ts b/src/Resources/app/administration/src/module/swag-migration/component/card/swag-migration-shop-information/index.ts new file mode 100644 index 000000000..9ad8e5158 --- /dev/null +++ b/src/Resources/app/administration/src/module/swag-migration/component/card/swag-migration-shop-information/index.ts @@ -0,0 +1,484 @@ +import template from './swag-migration-shop-information.html.twig'; +import './swag-migration-shop-information.scss'; +import type { + MigrationConnection, + MigrationProfile, + TEntity, + TEntityCollection, + TRepository, +} from '../../../../../type/types'; +import { MIGRATION_API_SERVICE } from '../../../../../core/service/api/swag-migration.api.service'; +import { MIGRATION_STORE_ID, type MigrationStore } from '../../../store/migration.store'; + +const { Mixin, Store } = Shopware; +const { mapState } = Shopware.Component.getComponentHelper(); +const { format } = Shopware.Utils; +const { Criteria } = Shopware.Data; + +/** + * @private + */ +export const BADGE_TYPE = { + SUCCESS: 'success', + DANGER: 'danger', +} as const; + +const MIGRATION_POLLING_INTERVAL = 2500 as const; + +type PollingType = 'checksum' | 'truncate'; + +/** + * @private + */ +export interface SwagMigrationShopInformationData { + migrationStore: MigrationStore; + confirmModalIsLoading: boolean; + showRemoveCredentialsConfirmModal: boolean; + showResetChecksumsConfirmModal: boolean; + showResetMigrationConfirmModal: boolean; + lastMigrationDate: string; + connection: MigrationConnection | null; + context: unknown; + checksumPollingIntervalId: number | null; + truncatePollingIntervalId: number | null; + isLoading: boolean; +} + +/** + * @private + * @sw-package fundamentals@after-sales + */ +export default Shopware.Component.wrapComponentConfig({ + template, + + inject: [ + MIGRATION_API_SERVICE, + 'repositoryFactory', + 'acl', + ], + + mixins: [ + Mixin.getByName('notification'), + ], + + props: { + connected: { + type: Boolean, + default: false, + }, + }, + + data(): SwagMigrationShopInformationData { + return { + migrationStore: Store.get(MIGRATION_STORE_ID), + checksumPollingIntervalId: null, + truncatePollingIntervalId: null, + confirmModalIsLoading: false, + showRemoveCredentialsConfirmModal: false, + showResetChecksumsConfirmModal: false, + showResetMigrationConfirmModal: false, + lastMigrationDate: '-', + connection: null, + context: Shopware.Context.api, + isLoading: false, + }; + }, + + computed: { + ...mapState( + () => Store.get(MIGRATION_STORE_ID), + [ + 'isResettingChecksum', + 'isTruncatingMigration', + 'connectionId', + 'currentConnection', + 'environmentInformation', + 'lastConnectionCheck', + 'adminLocaleLanguage', + 'adminLocaleRegion', + ], + ), + + migrationRunRepository(): TRepository<'swag_migration_run'> { + return this.repositoryFactory.create('swag_migration_run'); + }, + + migrationConnectionRepository(): TRepository<'swag_migration_connection'> { + return this.repositoryFactory.create('swag_migration_connection'); + }, + + migrationGeneralSettingRepository(): TRepository<'swag_migration_general_setting'> { + return this.repositoryFactory.create('swag_migration_general_setting'); + }, + + displayEnvironmentInformation() { + return this.environmentInformation === null ? {} : this.environmentInformation; + }, + + isUpdating() { + return this.isResettingChecksum || this.isTruncatingMigration || this.isLoading; + }, + + showUpdateBanner() { + return this.isResettingChecksum || this.isTruncatingMigration; + }, + + updateBannerTitle() { + if (this.isResettingChecksum) { + return this.$tc('swag-migration.index.shopInfoCard.updateBanner.isResettingChecksums.title'); + } + + if (this.isTruncatingMigration) { + return this.$tc('swag-migration.index.shopInfoCard.updateBanner.isTruncatingMigration.title'); + } + + return ''; + }, + + updateBannerMessage() { + if (this.isResettingChecksum) { + return this.$tc('swag-migration.index.shopInfoCard.updateBanner.isResettingChecksums.message'); + } + + if (this.isTruncatingMigration) { + return this.$tc('swag-migration.index.shopInfoCard.updateBanner.isTruncatingMigration.message'); + } + + return ''; + }, + + connectionName() { + return this.connection !== null + ? this.connection.name + : this.$tc('swag-migration.index.shopInfoCard.noConnection'); + }, + + connectionBadgeLabel() { + if (this.serverUnreachable) { + return 'swag-migration.index.shopInfoCard.serverUnreachable'; + } + + if (this.connected) { + return 'swag-migration.index.shopInfoCard.connected'; + } + + return 'swag-migration.index.shopInfoCard.notConnected'; + }, + + connectionBadgeVariant() { + if (this.connected) { + return BADGE_TYPE.SUCCESS; + } + + return BADGE_TYPE.DANGER; + }, + + shopUrl() { + return this.displayEnvironmentInformation.sourceSystemDomain === undefined + ? '' + : this.displayEnvironmentInformation.sourceSystemDomain.replace(/^\s*https?:\/\//, ''); + }, + + shopUrlPrefix() { + if (this.displayEnvironmentInformation.sourceSystemDomain === undefined) { + return ''; + } + + const match = this.displayEnvironmentInformation.sourceSystemDomain.match(/^\s*https?:\/\//); + + if (match === null) { + return ''; + } + + return match[0]; + }, + + sslActive() { + return this.shopUrlPrefix === 'https://'; + }, + + shopUrlPrefixClass() { + return this.sslActive ? 'swag-migration-shop-information__shop-domain-prefix--is-ssl' : ''; + }, + + shopFirstLetter() { + return this.displayEnvironmentInformation.sourceSystemName?.charAt(0) ?? 'S'; + }, + + profile() { + return this.connection === null || this.connection.profile === undefined + ? '' + : // eslint-disable-next-line max-len + `${this.connection.profile.sourceSystemName} ${this.connection.profile.version} - ${this.connection.profile.author}`; + }, + + profileIcon() { + return this.connection === null || + this.connection.profile === undefined || + this.connection.profile.icon === undefined + ? null + : this.connection.profile.icon; + }, + + gateway() { + return this.connection === null || this.connection.gateway === undefined ? '' : this.connection.gateway.snippet; + }, + + formattedLastConnectionCheckDate() { + return format.date(this.lastConnectionCheck); + }, + + formattedLastMigrationDateTime() { + return format.date(this.lastMigrationDate); + }, + + assetFilter() { + return Shopware.Filter.getByName('asset'); + }, + + showMoreInformation() { + return this.connection !== null; + }, + }, + + watch: { + $route: { + immediate: true, + handler() { + this.showResetMigrationConfirmModal = this.$route.meta.resetMigration; + }, + }, + + connectionId: { + immediate: true, + handler(newConnectionId: string) { + this.fetchConnection(newConnectionId); + }, + }, + }, + + created() { + this.createdComponent(); + }, + + methods: { + async createdComponent() { + this.isLoading = true; + + try { + const [ + isResettingChecksums, + isTruncatingMigration, + ] = await Promise.all([ + this.migrationApiService.isResettingChecksums(), + this.migrationApiService.isTruncatingMigrationData(), + this.updateLastMigrationDate(), + ]); + + if (isResettingChecksums) { + this.registerPolling('checksum'); + } + + if (isTruncatingMigration) { + this.registerPolling('truncate'); + } + } finally { + this.isLoading = false; + } + }, + + async updateLastMigrationDate() { + const storedRun = Shopware.Store.get(MIGRATION_STORE_ID).latestRun; + + if (storedRun) { + this.lastMigrationDate = storedRun.createdAt; + return Promise.resolve(); + } + + const criteria = new Criteria(1, 1).addSorting(Criteria.sort('createdAt', 'DESC')); + + return this.migrationRunRepository + .search(criteria, this.context) + .then((runs: TEntityCollection<'swag_migration_run'>) => { + if (runs.length > 0) { + this.lastMigrationDate = runs.first().createdAt; + Shopware.Store.get(MIGRATION_STORE_ID).setLatestRun(runs.first()); + } else { + this.lastMigrationDate = '-'; + } + }); + }, + + async fetchConnection(connectionId: string | null) { + if (!connectionId) { + return Promise.resolve(); + } + + if (this.currentConnection) { + this.connection = this.currentConnection; + return Promise.resolve(); + } + + return this.migrationConnectionRepository + .get(connectionId, this.context) + .then((connection: TEntity<'swag_migration_connection'>) => { + if (!connection) { + return Promise.resolve(null); + } + + delete connection.credentialFields; + this.connection = connection; + Shopware.Store.get(MIGRATION_STORE_ID).setCurrentConnection(connection); + + return this.migrationApiService.getProfileInformation(connection.profileName, connection.gatewayName); + }) + .then((profileInformation: MigrationProfile) => { + if (!profileInformation) { + return; + } + + this.connection.profile = profileInformation.profile; + this.connection.gateway = profileInformation.gateway; + }); + }, + + registerPolling(type: PollingType) { + this.unregisterPolling(type); + + if (type === 'checksum') { + this.migrationStore.setIsResettingChecksum(true); + this.checksumPollingIntervalId = setInterval(() => this.poll(type), MIGRATION_POLLING_INTERVAL); + } else { + this.migrationStore.setIsTruncatingMigration(true); + this.truncatePollingIntervalId = setInterval(() => this.poll(type), MIGRATION_POLLING_INTERVAL); + } + }, + + unregisterPolling(type: PollingType) { + if (type === 'checksum') { + if (this.checksumPollingIntervalId) { + clearInterval(this.checksumPollingIntervalId); + } + + this.checksumPollingIntervalId = null; + this.migrationStore.setIsResettingChecksum(false); + } else { + if (this.truncatePollingIntervalId) { + clearInterval(this.truncatePollingIntervalId); + } + + this.migrationStore.setIsTruncatingMigration(false); + this.truncatePollingIntervalId = null; + } + }, + + async poll(type: PollingType) { + const isActive = type === 'checksum' ? this.isResettingChecksum : this.isTruncatingMigration; + + if (!isActive) { + return; + } + + try { + const isStillRunning = + type === 'checksum' + ? await this.migrationApiService.isResettingChecksums() + : await this.migrationApiService.isTruncatingMigrationData(); + + if (!isStillRunning) { + this.unregisterPolling(type); + + if (type === 'truncate') { + await this.migrationStore.init( + this.migrationApiService, + this.migrationGeneralSettingRepository, + true, + ); + } + } + } catch { + this.unregisterPolling(type); + this.createNotificationError({ + title: this.$tc('global.default.error'), + message: this.$tc('swag-migration.api-error.getState'), + }); + } + }, + + openResetMigrationModal() { + this.showResetMigrationConfirmModal = true; + }, + + async onCloseResetModal() { + this.showResetMigrationConfirmModal = false; + await this.$router.push({ + name: 'swag.migration.index.main', + }); + }, + + onClickEditConnectionCredentials() { + this.$router.push({ + name: 'swag.migration.wizard.credentials', + params: { + connectionId: this.connectionId, + }, + }); + }, + + onClickCreateConnection() { + this.$router.push({ + name: 'swag.migration.wizard.connectionCreate', + }); + }, + + onClickCreateInitialConnection() { + this.$router.push({ + name: 'swag.migration.wizard.introduction', + }); + }, + + onClickSelectConnection() { + this.$router.push({ + name: 'swag.migration.wizard.connectionSelect', + }); + }, + + onClickProfileInstallation() { + this.$router.push({ + name: 'swag.migration.wizard.profileInstallation', + }); + }, + + async onClickRefreshConnection() { + await this.migrationStore.init(this.migrationApiService, this.migrationGeneralSettingRepository, true); + }, + + async onClickRemoveConnectionCredentials() { + this.confirmModalIsLoading = true; + + return this.migrationApiService.updateConnectionCredentials(this.connectionId, {}).then(() => { + this.$router.go(); + }); + }, + + async onClickResetChecksums() { + this.confirmModalIsLoading = true; + + await this.migrationApiService.resetChecksums(this.connectionId); + this.registerPolling('checksum'); + + this.showResetChecksumsConfirmModal = false; + this.confirmModalIsLoading = false; + }, + + async onClickResetMigration() { + this.confirmModalIsLoading = true; + + await this.migrationApiService.cleanupMigrationData(); + this.registerPolling('truncate'); + + this.showResetMigrationConfirmModal = false; + this.confirmModalIsLoading = false; + }, + }, +}); diff --git a/src/Resources/app/administration/src/module/swag-migration/component/card/swag-migration-shop-information/swag-migration-shop-information.html.twig b/src/Resources/app/administration/src/module/swag-migration/component/card/swag-migration-shop-information/swag-migration-shop-information.html.twig index 4803fd11b..afac4e53f 100644 --- a/src/Resources/app/administration/src/module/swag-migration/component/card/swag-migration-shop-information/swag-migration-shop-information.html.twig +++ b/src/Resources/app/administration/src/module/swag-migration/component/card/swag-migration-shop-information/swag-migration-shop-information.html.twig @@ -1,52 +1,58 @@ {% block swag_migration_shop_information %} + + {{ updateBannerMessage }} + + -