diff --git a/.git_hooks/external_runtime b/.git_hooks/external_runtime deleted file mode 100644 index 7569e89..0000000 --- a/.git_hooks/external_runtime +++ /dev/null @@ -1,37 +0,0 @@ -#!/bin/bash - -############################################################################### -# External Runtime - вспомогательный скрипт для запуска хуков в отдельной # -# среде, например в контейнере. # -# Использование: # -# 1. Подключите этот файл в скрипт хука: # -# source . $(pwd)/.git_hooks/external_runtime # -# 2. Создайте выше по файловой системе файл .external-runtime, # -# содержащий переменную EXTERNAL_RUNTIME_COMMAND, например: # -# EXTERNAL_RUNTIME_COMMAND="ensi exec-script" -# Этот файл должен отсутствовать в среде запуска. -############################################################################### - -EXTERNAL_RUNTIME_FILE=".external-runtime" - -ESC_SEQ="\x1b[" -COL_RESET=$ESC_SEQ"39;49;00m" -COL_BLUE=$ESC_SEQ"0;34m" - -findUp () { - path=$(pwd) - while [[ "$path" != "" && ! -e "$path/$1" ]]; do - path=${path%/*} - done - echo "$path" -} - -# search external runtime file -rcpath=$(findUp "$EXTERNAL_RUNTIME_FILE") -if [[ "$rcpath" != "" ]]; then - # source it and run hook in via runtime command - . $rcpath/$EXTERNAL_RUNTIME_FILE - printf "$COL_BLUE%s$COL_RESET\n" "External runtime has been found. Running hook with '$EXTERNAL_RUNTIME_COMMAND' command" - $EXTERNAL_RUNTIME_COMMAND $0 - exit $? -fi \ No newline at end of file diff --git a/.git_hooks/post-checkout/01-install-dependencies.sh b/.git_hooks/post-checkout/01-install-dependencies.sh new file mode 120000 index 0000000..43a65ea --- /dev/null +++ b/.git_hooks/post-checkout/01-install-dependencies.sh @@ -0,0 +1 @@ +../scripts/install-dependencies.sh \ No newline at end of file diff --git a/.git_hooks/post-checkout/install-dependencies.sh b/.git_hooks/post-checkout/install-dependencies.sh deleted file mode 100755 index 775fa37..0000000 --- a/.git_hooks/post-checkout/install-dependencies.sh +++ /dev/null @@ -1,19 +0,0 @@ -#!/bin/bash - -source $(pwd)/.git_hooks/external_runtime - -ESC_SEQ="\x1b[" -COL_RESET=$ESC_SEQ"39;49;00m" -COL_RED=$ESC_SEQ"0;31m" -COL_GREEN=$ESC_SEQ"0;32m" -COL_YELLOW=$ESC_SEQ"0;33m" - -changed_files="$(git diff-tree -r --name-only --no-commit-id HEAD@{1} HEAD)" - -check_run() { - echo "$changed_files" | grep --quiet "$1" && echo " * changes detected in $1" && echo " * running $2" && eval "$2" -} - -check_run composer.lock "composer install" -check_run package-lock.json "npm install" -exit 0 diff --git a/.git_hooks/post-merge/01-install-dependencies.sh b/.git_hooks/post-merge/01-install-dependencies.sh new file mode 120000 index 0000000..43a65ea --- /dev/null +++ b/.git_hooks/post-merge/01-install-dependencies.sh @@ -0,0 +1 @@ +../scripts/install-dependencies.sh \ No newline at end of file diff --git a/.git_hooks/post-merge/install-dependencies.sh b/.git_hooks/post-merge/install-dependencies.sh deleted file mode 100755 index 775fa37..0000000 --- a/.git_hooks/post-merge/install-dependencies.sh +++ /dev/null @@ -1,19 +0,0 @@ -#!/bin/bash - -source $(pwd)/.git_hooks/external_runtime - -ESC_SEQ="\x1b[" -COL_RESET=$ESC_SEQ"39;49;00m" -COL_RED=$ESC_SEQ"0;31m" -COL_GREEN=$ESC_SEQ"0;32m" -COL_YELLOW=$ESC_SEQ"0;33m" - -changed_files="$(git diff-tree -r --name-only --no-commit-id HEAD@{1} HEAD)" - -check_run() { - echo "$changed_files" | grep --quiet "$1" && echo " * changes detected in $1" && echo " * running $2" && eval "$2" -} - -check_run composer.lock "composer install" -check_run package-lock.json "npm install" -exit 0 diff --git a/.git_hooks/pre-commit/01-lint-php.sh b/.git_hooks/pre-commit/01-lint-php.sh new file mode 120000 index 0000000..5833040 --- /dev/null +++ b/.git_hooks/pre-commit/01-lint-php.sh @@ -0,0 +1 @@ +../scripts/lint-php.sh \ No newline at end of file diff --git a/.git_hooks/pre-commit/02-php-cs-fixer.sh b/.git_hooks/pre-commit/02-php-cs-fixer.sh new file mode 120000 index 0000000..66c2032 --- /dev/null +++ b/.git_hooks/pre-commit/02-php-cs-fixer.sh @@ -0,0 +1 @@ +../scripts/php-cs-fixer.sh \ No newline at end of file diff --git a/.git_hooks/pre-push/01-composer-validate.sh b/.git_hooks/pre-push/01-composer-validate.sh new file mode 120000 index 0000000..61e981f --- /dev/null +++ b/.git_hooks/pre-push/01-composer-validate.sh @@ -0,0 +1 @@ +../scripts/composer-validate.sh \ No newline at end of file diff --git a/.git_hooks/pre-push/02-phpstan.sh b/.git_hooks/pre-push/02-phpstan.sh new file mode 120000 index 0000000..05c8a9b --- /dev/null +++ b/.git_hooks/pre-push/02-phpstan.sh @@ -0,0 +1 @@ +../scripts/phpstan.sh \ No newline at end of file diff --git a/.git_hooks/pre-push/03-test-code.sh b/.git_hooks/pre-push/03-test-code.sh new file mode 120000 index 0000000..b33ab89 --- /dev/null +++ b/.git_hooks/pre-push/03-test-code.sh @@ -0,0 +1 @@ +../scripts/test-code.sh \ No newline at end of file diff --git a/.git_hooks/pre-push/var-dump-checker.sh b/.git_hooks/pre-push/var-dump-checker.sh deleted file mode 100755 index 4303706..0000000 --- a/.git_hooks/pre-push/var-dump-checker.sh +++ /dev/null @@ -1,23 +0,0 @@ -#!/bin/bash - -source $(pwd)/.git_hooks/external_runtime - -ESC_SEQ="\x1b[" -COL_RESET=$ESC_SEQ"39;49;00m" -COL_RED=$ESC_SEQ"0;31m" -COL_GREEN=$ESC_SEQ"0;32m" -COL_YELLOW=$ESC_SEQ"0;33m" - -echo -printf "$COL_YELLOW%s$COL_RESET\n" "Running pre-push hook: \"var-dump-checker\"" - -./vendor/bin/var-dump-check --laravel --exclude bootstrap --exclude node_modules --exclude vendor . - -# If the grep command has no hits - echo a warning and exit with non-zero status. -if [ $? == 1 ]; then - printf "$COL_RED%s$COL_RESET\r\n\r\n" "Some var_dump usage found. Please fix your code" - exit 1 -fi - -echo "Okay" -exit 0 diff --git a/.git_hooks/pre-push/composer-validate.sh b/.git_hooks/scripts/composer-validate.sh similarity index 86% rename from .git_hooks/pre-push/composer-validate.sh rename to .git_hooks/scripts/composer-validate.sh index b32cd69..543451a 100755 --- a/.git_hooks/pre-push/composer-validate.sh +++ b/.git_hooks/scripts/composer-validate.sh @@ -1,8 +1,6 @@ #!/bin/bash -source $(pwd)/.git_hooks/external_runtime - -# validate composer +# Validate composer.json before commit ESC_SEQ="\x1b[" COL_RESET=$ESC_SEQ"39;49;00m" @@ -10,7 +8,7 @@ COL_RED=$ESC_SEQ"0;31m" COL_GREEN=$ESC_SEQ"0;32m" COL_YELLOW=$ESC_SEQ"0;33m" -echo +echo printf "$COL_YELLOW%s$COL_RESET\n" "Running pre-push hook: \"composer-validate\"" VALID=$(composer validate --strict --no-check-publish --no-check-all | grep "is valid") diff --git a/.git_hooks/scripts/install-dependencies.sh b/.git_hooks/scripts/install-dependencies.sh new file mode 100755 index 0000000..3b308e5 --- /dev/null +++ b/.git_hooks/scripts/install-dependencies.sh @@ -0,0 +1,18 @@ +#!/bin/bash + +# - 'composer update' if changed composer.json + +ESC_SEQ="\x1b[" +COL_RESET=$ESC_SEQ"39;49;00m" +COL_RED=$ESC_SEQ"0;31m" +COL_GREEN=$ESC_SEQ"0;32m" +COL_YELLOW=$ESC_SEQ"0;33m" + +changed_files="$(git diff-tree -r --name-only --no-commit-id HEAD@{1} HEAD)" + +check_run() { + echo "$changed_files" | grep -q "$1" && echo " * changes detected in $1" && echo " * running $2" && eval "$2" +} + +check_run composer.json "composer update" +exit 0 diff --git a/.git_hooks/pre-commit/lint-php.sh b/.git_hooks/scripts/lint-php.sh similarity index 94% rename from .git_hooks/pre-commit/lint-php.sh rename to .git_hooks/scripts/lint-php.sh index ee6838f..2850447 100755 --- a/.git_hooks/pre-commit/lint-php.sh +++ b/.git_hooks/scripts/lint-php.sh @@ -1,6 +1,6 @@ #!/bin/bash -source $(pwd)/.git_hooks/external_runtime +# Lint all added php-files via 'php -l' ROOT_DIR="$(pwd)/" LIST=$(git diff-index --cached --name-only --diff-filter=ACMR HEAD) @@ -33,13 +33,13 @@ do fi done if [ "$ERRORS_BUFFER" != "" ]; then - echo + echo echo "These errors were found in try-to-commit files: " echo -e $ERRORS_BUFFER - echo + echo printf "$COL_RED%s$COL_RESET\r\n\r\n" "Can't commit, fix errors first." exit 1 else echo "Okay" exit 0 -fi \ No newline at end of file +fi diff --git a/.git_hooks/pre-commit/php-cs-fixer.sh b/.git_hooks/scripts/php-cs-fixer.sh similarity index 97% rename from .git_hooks/pre-commit/php-cs-fixer.sh rename to .git_hooks/scripts/php-cs-fixer.sh index cf98161..3fe095a 100755 --- a/.git_hooks/pre-commit/php-cs-fixer.sh +++ b/.git_hooks/scripts/php-cs-fixer.sh @@ -1,6 +1,6 @@ #!/bin/bash -source $(pwd)/.git_hooks/external_runtime +# Check code style via '.php-cs-fixer.php' EXECUTABLE_NAME=php-cs-fixer EXECUTABLE_COMMAND=fix diff --git a/.git_hooks/scripts/phpstan.sh b/.git_hooks/scripts/phpstan.sh new file mode 100755 index 0000000..7c15b55 --- /dev/null +++ b/.git_hooks/scripts/phpstan.sh @@ -0,0 +1,20 @@ +#!/bin/bash + +# Run composer phpstan + +ESC_SEQ="\x1b[" +COL_RESET=$ESC_SEQ"39;49;00m" +COL_RED=$ESC_SEQ"0;31m" +COL_GREEN=$ESC_SEQ"0;32m" +COL_YELLOW=$ESC_SEQ"0;33m" + +echo +printf "$COL_YELLOW%s$COL_RESET\n" "Running pre-push hook: \"phpstan\"" + +if composer phpstan; then + echo "Okay" + exit 0 +else + printf "$COL_RED%s$COL_RESET\r\n" "phpstan analysis failed." + exit 1 +fi diff --git a/.git_hooks/pre-push/test-code.sh b/.git_hooks/scripts/test-code.sh similarity index 89% rename from .git_hooks/pre-push/test-code.sh rename to .git_hooks/scripts/test-code.sh index ac102a3..faa22a1 100755 --- a/.git_hooks/pre-push/test-code.sh +++ b/.git_hooks/scripts/test-code.sh @@ -1,6 +1,6 @@ #!/bin/bash -source $(pwd)/.git_hooks/external_runtime +# Run composer test ESC_SEQ="\x1b[" COL_RESET=$ESC_SEQ"39;49;00m" diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md new file mode 100644 index 0000000..8169284 --- /dev/null +++ b/.github/CONTRIBUTING.md @@ -0,0 +1,53 @@ +# Contributing + +Contributions are **welcome** and will be fully **credited**. + +Please read and understand the contribution guide before creating an issue or pull request. + +## Etiquette + +This project is open source, and as such, the maintainers give their free time to build and maintain the source code +held within. They make the code freely available in the hope that it will be of use to other developers. It would be +extremely unfair for them to suffer abuse or anger for their hard work. + +Please be considerate towards maintainers when raising issues or presenting pull requests. Let's show the +world that developers are civilized and selfless people. + +It's the duty of the maintainer to ensure that all submissions to the project are of sufficient +quality to benefit the project. Many developers have different skillsets, strengths, and weaknesses. Respect the maintainer's decision, and do not be upset or abusive if your submission is not used. + +## Viability + +When requesting or submitting new features, first consider whether it might be useful to others. Open +source projects are used by many developers, who may have entirely different needs to your own. Think about +whether or not your feature is likely to be used by other users of the project. + +## Procedure + +Before filing an issue: + +- Attempt to replicate the problem, to ensure that it wasn't a coincidental incident. +- Check to make sure your feature suggestion isn't already present within the project. +- Check the pull requests tab to ensure that the bug doesn't have a fix in progress. +- Check the pull requests tab to ensure that the feature isn't already in progress. + +Before submitting a pull request: + +- Check the codebase to ensure that your feature doesn't already exist. +- Check the pull requests to ensure that another person hasn't already submitted the feature or fix. + +## Requirements + +If the project maintainer has any additional requirements, you will find them listed here. + +- **Add tests!** - Your patch won't be accepted if it doesn't have tests. + +- **Document any change in behaviour** - Make sure the `README.md` and any other relevant documentation are kept up-to-date. + +- **Consider our release cycle** - We try to follow [SemVer v2.0.0](https://semver.org/). Randomly breaking public APIs is not an option. + +- **One pull request per feature** - If you want to do more than one thing, send multiple pull requests. + +- **Send coherent history** - Make sure each individual commit in your pull request is meaningful. If you had to make multiple intermediate commits while developing, please [squash them](https://www.git-scm.com/book/en/v2/Git-Tools-Rewriting-History#Changing-Multiple-Commit-Messages) before submitting. + +**Happy coding**! diff --git a/.github/SECURITY.md b/.github/SECURITY.md new file mode 100644 index 0000000..79c6717 --- /dev/null +++ b/.github/SECURITY.md @@ -0,0 +1,3 @@ +# Security Policy + +If you discover any security related issues, please email mail@greensight.ru instead of using the issue tracker. \ No newline at end of file diff --git a/.github/workflows/run-tests.yml b/.github/workflows/run-tests.yml index d0abbcc..8cc5b7e 100644 --- a/.github/workflows/run-tests.yml +++ b/.github/workflows/run-tests.yml @@ -13,22 +13,8 @@ jobs: fail-fast: true matrix: php: [8.1, 8.2, 8.3] - laravel: [8.*, 9.*, 10.*, 11.*] - include: - - laravel: 8.* - testbench: ^6.23 - - laravel: 9.* - testbench: 7.* - - laravel: 10.* - testbench: 8.* - - laravel: 11.* - testbench: 9.* + laravel: [9.*, 10.*, 11.*] exclude: - - laravel: 10.* - php: 8.0 - - - laravel: 11.* - php: 8.0 - laravel: 11.* php: 8.1 @@ -52,7 +38,14 @@ jobs: echo "::add-matcher::${{ runner.tool_cache }}/phpunit.json" - name: Install dependencies run: | - composer require "laravel/framework:${{ matrix.laravel }}" "orchestra/testbench:${{ matrix.testbench }}" --no-interaction --no-update + composer require "laravel/framework:${{ matrix.laravel }}" --no-interaction --no-update composer update --prefer-stable --prefer-dist --no-interaction + + - name: Composer Validate + run: ./.git_hooks/scripts/composer-validate.sh + - name: Execute tests - run: vendor/bin/pest + run: composer test-ci + + - name: Execute phpstan + run: ./.git_hooks/scripts/phpstan.sh diff --git a/.gitignore b/.gitignore index 19dce8e..daa725d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,15 +1,85 @@ -# IDE +# Project # +######################## +.php_cs.cache +.php-cs-fixer.cache +.huskyrc +clients/* +!clients/.gitkeep +storage/ensi +generated +studio.json +build +/node_modules +/vendor +.phpunit.result.cache +composer.lock +composer.local.json +Homestead.json +Homestead.yaml +npm-debug.log +yarn-error.log + +# IDEs # +################### *.sublime-project *.sublime-workspace -/.idea/ +/.idea +/.vscode *.komodoproject .vscode -.phpunit.result.cache -.php-cs-fixer.cache -composer.lock -build -generated -vendor -node_modules -coverage +# Static content # +################### +*.csv +*.pdf +*.doc +*.docx +*.xls +*.xlsx +*.xml +!phpunit.xml +!psalm.xml +*.yml +*.txt +*.wav +*.mp3 +*.avi + +# Compiled source # +################### +*.com +*.class +*.dll +*.exe +*.o +*.so +*.box + +# Packages # +############ +# it's better to unpack these files and commit the raw source +# git has its own built in compression methods +*.7z +*.dmg +*.gz +*.tgz +*.iso +*.jar +*.rar +*.tar +*.zip +*.phar + +# OS generated files # +###################### +.DS_Store +.DS_Store? +.nfs* +._* +.Spotlight-V100 +.Trashes +.vagrant +ehthumbs.db +Thumbs.db +sftp-config.json +auth.json \ No newline at end of file diff --git a/.huskyrc.json b/.huskyrc.json deleted file mode 100644 index 9feb8ef..0000000 --- a/.huskyrc.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "hooks": { - "post-checkout": ".git_hooks/post-checkout/install-dependencies.sh", - "post-merge": ".git_hooks/post-merge/install-dependencies.sh", - "pre-commit": ".git_hooks/pre-commit/lint-php.sh && .git_hooks/pre-commit/php-cs-fixer.sh", - "pre-push": ".git_hooks/pre-push/composer-validate.sh && .git_hooks/pre-push/var-dump-checker.sh && .git_hooks/pre-push/test-code.sh" - } -} \ No newline at end of file diff --git a/.php-cs-fixer.php b/.php-cs-fixer.php index 9a110fe..a2dce95 100644 --- a/.php-cs-fixer.php +++ b/.php-cs-fixer.php @@ -13,12 +13,15 @@ return (new PhpCsFixer\Config()) ->setRules([ '@PSR2' => true, + '@PSR12' => true, 'array_syntax' => ['syntax' => 'short'], 'ordered_imports' => ['sort_algorithm' => 'alpha'], 'no_unused_imports' => true, 'trailing_comma_in_multiline' => true, 'phpdoc_scalar' => true, 'unary_operator_spaces' => true, + 'binary_operator_spaces' => true, + 'concat_space' => ['spacing' => 'one'], 'blank_line_before_statement' => [ 'statements' => ['break', 'continue', 'declare', 'return', 'throw', 'try'], ], @@ -36,6 +39,6 @@ 'single_trait_insert_per_statement' => true, 'no_whitespace_in_blank_line' => true, 'method_chaining_indentation' => true, - + 'single_space_around_construct' => true, ]) ->setFinder($finder); diff --git a/LICENSE.md b/LICENSE.md index 24924fd..2ed94d2 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -1,19 +1,75 @@ -Copyright (c) 2020-present Greensight - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. +Открытая лицензия на право использования программы для ЭВМ Greensight Ecom Platform (GEP) + +1. Преамбула + +1.1. Общество с ограниченной ответственностью «ГринСайт», в лице генерального директора Волкова Егора Владимировича, действующего на основании Устава, публикует условия публичной оферты о предоставлении открытой лицензии на право использования программы для ЭВМ Greensight Ecom Platform (GEP) (далее — Ensi) в соответствии с условиями ст. 1286.1 Гражданского кодекса РФ (далее — Оферта). + +1.2. Правообладателем Ensi является ООО «ГринСайт» (далее — Правообладатель), в соответствии со свидетельством о государственной регистрации программы для ЭВМ № 2 020 663 096 от 22.10.2020 г. + +1.3. В соответствии с пунктом 2 статьи 437 Гражданского кодекса РФ в случае принятия изложенных в Оферте условий Правообладателя, юридическое или физическое лицо, производящее акцепт Оферты, становится лицензиатом (в соответствии с пунктом 3 статьи 438 ГК РФ акцепт оферты равносилен заключению договора на условиях, изложенных в оферте), а Правообладатель и лицензиат совместно — сторонами лицензионного договора. + +1.4. Вся документация, функциональные задания, сервисы и исходные коды Ensi размещены в сети Интернет по адресам: https://ensi.tech/ https://gitlab.com/greensight/ensi (далее — Сайт платформы). + +1.5. Правообладатель является участником проекта «Сколково» и предоставляет права использования Ensi в рамках коммерциализации результатов своих исследований и разработок по направлению «стратегические компьютерные технологии и программное обеспечение». + +2. Порядок акцепта оферты + +2.1. Лицензионный договор, заключаемый на основании акцептирования лицензиатом Оферты (далее — Лицензионный договор), является договором присоединения, к которому лицензиат присоединяется без каких-либо исключений и/или оговорок. + +2.2. Акцепт Оферты происходит в момент скачивания материалов Ensi с Сайта платформы. + +2.3. Срок акцепта Оферты не ограничен. + +3. Перечень прав использования Ensi + +3.1. При соблюдении лицензиатом требований раздела 4 Оферты, предоставляемое право использования ENSI включает в себя: + +3.1.1. Право использования Ensi на технических средствах лицензиата в соответствии с назначением Ensi, в том числе, все права использования, предусмотренные ст. 1280 Гражданского кодекса РФ; + +3.1.2. Право на воспроизведение Ensi, не ограниченное правом его инсталляции и запуска; + +3.1.3. Право на модификацию, адаптацию, внесение изменений и создание производных произведений (сложных произведений) с Ensi. + +3.2. Лицензиату предоставляется право передачи третьим лицам прав, указанных в п. 3.1 Оферты (право сублицензирования). + +3.3. Действие Лицензионного договора — территория всего мира. + +3.4. Право использования Ensi предоставляется лицензиату на весь срок действия исключительных прав Правообладателя. + +3.5. Право использования Ensi предоставляется безвозмездно. Лицензиат вправе использовать Ensi для создания производных произведений (сложных произведений) и их коммерческого применения, с учетом ограничений раздела 4 Оферты. + +4. Обязанности лицензиата + +4.1. Лицензиату предоставляются права указанные в разделе 3 Оферты при соблюдении им следующих условий: + +4.1.1. Наличия письменного указания на авторство Правообладателя и ссылки на Сайт платформы при реализации третьим лицам Ensi (в коммерческих или некоммерческих целях), а также в любых созданных производных от Ensi произведениях. + +4.1.2. Сохранения неизменным следующих частей кода Ensi: +- в файле src/pages/_app.tsx строка — <meta name="generator" content="Ensi Platform" /> +- в файле next.config.js строка — return [{ source: '/(.*)', headers: [{ key: 'X-Ensi-Platform', value: '1' }] }]; + +Удаление данных частей кода будет является существенным нарушением условий Оферты. + +4.1.3. Использования Ensi в законных целях, а именно: не нарушающих законодательство Российской Федерации, норм международных договоров Российской Федерации, общепризнанных принципов и норм международного права. Не допускается использование Ensi в проектах, противоречащих принципам гуманности и морали, в распространении материалов и информации запрещенных в Российской Федерации. + +4.2. При нарушении лицензиатом условий п. 4.1 Оферты, Правообладатель вправе в одностороннем порядке расторгнуть Лицензионный договор и потребовать мер защиты исключительных прав, включая положения ст.ст. 1252, 1301 Гражданского кодекса РФ. + +4.3. Лицензиат дает Правообладателю согласие на указание своего фирменного наименования и логотипа на сайте Платформы. Правообладатель вправе использовать фирменное наименование и логотип Лицензиата в своих маркетинговых целях без дополнительного согласования с Лицензиатом. + +5. Ограничение ответственности + +5.1. Права использования Ensi предоставляются на условии «как есть» («as is») без какого-либо вида гарантий. Правообладатель не имеет обязательств перед лицензиатом по поддержанию функционирования Ensi в случае сбоя в работе, обеспечению отказоустойчивости и иных параметров, позволяющих использовать Ensi. Правообладатель не несет ответственности за любые убытки, упущенную выгоду, связанную с повреждением имущества, неполученным доходом, прерыванием коммерческой или производственной деятельности, возникшие вследствие использования Ensi лицензиатом. + +6. Заключительные положения + +6.1. Оферта вступает в силу с даты ее размещения на Сайте платформы и действует до момента прекращения исключительных прав на Ensi у Правообладателя. + +6.2. Переход исключительного права на Ensi к новому правообладателю не будет являться основанием для изменения или расторжения Лицензионного договора. + +6.3. К отношениям между Правообладателем и лицензиатом применяется право Российской Федерации. + +6.4. Реквизиты Правообладателя: +Общество с ограниченной ответственностью «ГринСайт» +ОГРН 11 087 746 328 812 +ИНН 7 735 538 694 +КПП 773 501 001 \ No newline at end of file diff --git a/README.md b/README.md index b2a99e0..4ee567a 100644 --- a/README.md +++ b/README.md @@ -1,16 +1,23 @@ # Laravel OpenApi Server Generator +[![Latest Version on Packagist](https://img.shields.io/packagist/v/ensi/laravel-openapi-server-generator.svg?style=flat-square)](https://packagist.org/packages/ensi/laravel-openapi-server-generator) +[![Tests](https://github.com/ensi-platform/laravel-php-rdkafka/actions/workflows/run-tests.yml/badge.svg?branch=master)](https://github.com/ensi-platform/laravel-php-rdkafka/actions/workflows/run-tests.yml) +[![Total Downloads](https://img.shields.io/packagist/dt/ensi/laravel-openapi-server-generator.svg?style=flat-square)](https://packagist.org/packages/ensi/laravel-openapi-server-generator) + Generates Laravel application code from Open Api Specification files ## Installation You can install the package via composer: -`composer require ensi/laravel-openapi-server-generator` - -Next you need to publish config file like this: +```bash +composer require ensi/laravel-openapi-server-generator --dev +``` -`php artisan vendor:publish --provider="Ensi\LaravelOpenApiServerGenerator\LaravelOpenApiServerGeneratorServiceProvider"` +Publish the config file with: +```bash +php artisan vendor:publish --provider="Ensi\LaravelOpenApiServerGenerator\LaravelOpenApiServerGeneratorServiceProvider" +``` and configure all the options. @@ -18,6 +25,16 @@ and configure all the options. Delete `config/openapi-server-generator.php`, republish it using command above and recreate desired configuration. +## Version Compatibility + +| Laravel OpenApi Server Generator | Laravel | PHP | +|----------------------------------|----------------------------|------------------| +| ^0.0.2 - ^0.8.2 | ^7.x | ^7.1.3 | +| ^0.8.3 - ^0.9.0 | ^7.x \|\| ^8.x | ^7.1.3 \|\| ^8.0 | +| ^1.0.0 - ^1.1.2 | * | ^8.0 | +| ^2.0.0 - ^3.0.3 | * | ^8.1 | +| ^4.0.0 | ^9.x \|\| ^10.x \|\| ^11.x | ^8.1 | + #### Basic Usage Run `php artisan openapi:generate-server`. It will generate all the configured entities from you OAS3 files. @@ -138,15 +155,12 @@ Please see [CONTRIBUTING](.github/CONTRIBUTING.md) for details. ### Testing 1. composer install -2. npm i -3. composer test +2. composer test ## Security Vulnerabilities -Please review [our security policy](../../security/policy) on how to report security vulnerabilities. +Please review [our security policy](.github/SECURITY.md) on how to report security vulnerabilities. ## License The MIT License (MIT). Please see [License File](LICENSE.md) for more information. - - diff --git a/composer.json b/composer.json index 82e08eb..3f2b62f 100644 --- a/composer.json +++ b/composer.json @@ -1,17 +1,21 @@ { "name": "ensi/laravel-openapi-server-generator", - "description": "", + "description": "laravel openapi server generator", "type": "library", - "authors": [ - { - "name": "Nekrasov Ilya", - "email": "nekrasov@greensight.ru" - } - ], "license": "MIT", "require": { "php": "^8.1", - "devizzent/cebe-php-openapi": "^1.0" + "devizzent/cebe-php-openapi": "^1.0", + "laravel/framework": "^9.0 || ^10.0 || ^11.0" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "^3.2", + "pestphp/pest": "^1.22 || ^2.0", + "pestphp/pest-plugin-laravel": "^1.1 || ^2.0", + "phpstan/extension-installer": "^1.3", + "phpstan/phpstan": "^1.11", + "spaze/phpstan-disallowed-calls": "^2.15", + "orchestra/testbench": "^7.0 || ^8.0 || ^9.0" }, "autoload": { "psr-4": { @@ -26,14 +30,12 @@ "Ensi\\LaravelOpenApiServerGenerator\\Tests\\": "tests" } }, - "require-dev": { - "friendsofphp/php-cs-fixer": "^3.2", - "mockery/mockery": ">=1.3.2", - "pestphp/pest": "^1.18 || ^2.0", - "pestphp/pest-plugin-laravel": "^1.1 || ^2.0", - "php-parallel-lint/php-var-dump-check": "^0.5.0", - "spatie/laravel-ray": "^1.23", - "orchestra/testbench": "^6.23 || ^7.0 || ^8.0 || ^9.0" + "scripts": { + "cs": "php-cs-fixer fix --config .php-cs-fixer.php", + "phpstan": "phpstan analyse", + "test": "./vendor/bin/pest --parallel --no-coverage", + "test-ci": "./vendor/bin/pest --no-coverage", + "test-coverage": "XDEBUG_MODE=coverage ./vendor/bin/pest --parallel --coverage" }, "extra": { "laravel": { @@ -42,16 +44,11 @@ ] } }, - "scripts": { - "cs": "php-cs-fixer fix --config .php-cs-fixer.php", - "test": "./vendor/bin/pest --no-coverage", - "test-coverage": "XDEBUG_MODE=coverage ./vendor/bin/pest --coverage" - }, "config": { "sort-packages": true, "allow-plugins": { - "composer/package-versions-deprecated": true, - "pestphp/pest-plugin": true + "pestphp/pest-plugin": true, + "phpstan/extension-installer": true } } } diff --git a/package-lock.json b/package-lock.json deleted file mode 100644 index 64ee072..0000000 --- a/package-lock.json +++ /dev/null @@ -1,905 +0,0 @@ -{ - "name": "laravel-openapi-server-generator", - "lockfileVersion": 2, - "requires": true, - "packages": { - "": { - "devDependencies": { - "husky": "^4.3.0" - } - }, - "node_modules/@babel/code-frame": { - "version": "7.15.8", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.15.8.tgz", - "integrity": "sha512-2IAnmn8zbvC/jKYhq5Ki9I+DwjlrtMPUCH/CpHvqI4dNnlwHwsxoIhlc8WcYY5LSYknXQtAlFYuHfqAFCvQ4Wg==", - "dev": true, - "dependencies": { - "@babel/highlight": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-identifier": { - "version": "7.15.7", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.15.7.tgz", - "integrity": "sha512-K4JvCtQqad9OY2+yTU8w+E82ywk/fe+ELNlt1G8z3bVGlZfn/hOcQQsUhGhW/N+tb3fxK800wLtKOE/aM0m72w==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/highlight": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.14.5.tgz", - "integrity": "sha512-qf9u2WFWVV0MppaL877j2dBtQIDgmidgjGk5VIMw3OadXvYaXn66U1BFlH2t4+t3i+8PhedppRv+i40ABzd+gg==", - "dev": true, - "dependencies": { - "@babel/helper-validator-identifier": "^7.14.5", - "chalk": "^2.0.0", - "js-tokens": "^4.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/highlight/node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/@babel/highlight/node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true - }, - "node_modules/@babel/highlight/node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@types/parse-json": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz", - "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==", - "dev": true - }, - "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/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/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/ci-info": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", - "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==", - "dev": true - }, - "node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/compare-versions": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/compare-versions/-/compare-versions-3.6.0.tgz", - "integrity": "sha512-W6Af2Iw1z4CB7q4uU4hv646dW9GQuBM+YpC0UvUCWSD8w90SJjp+ujJuXaEMtAXBtSqGfMPuFOVn4/+FlaqfBA==", - "dev": true - }, - "node_modules/cosmiconfig": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.0.1.tgz", - "integrity": "sha512-a1YWNUV2HwGimB7dU2s1wUMurNKjpx60HxBB6xUM8Re+2s1g1IIfJvFR0/iCF+XHdE0GMTKTuLR32UQff4TEyQ==", - "dev": true, - "dependencies": { - "@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": ">=10" - } - }, - "node_modules/error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "dev": true, - "dependencies": { - "is-arrayish": "^0.2.1" - } - }, - "node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", - "dev": true, - "engines": { - "node": ">=0.8.0" - } - }, - "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/find-versions": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/find-versions/-/find-versions-4.0.0.tgz", - "integrity": "sha512-wgpWy002tA+wgmO27buH/9KzyEOQnKsG/R0yrcjPT9BOFm0zRBVQbZ95nRGXWMywS8YR5knRbpohio0bcJABxQ==", - "dev": true, - "dependencies": { - "semver-regex": "^3.1.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "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/husky": { - "version": "4.3.8", - "resolved": "https://registry.npmjs.org/husky/-/husky-4.3.8.tgz", - "integrity": "sha512-LCqqsB0PzJQ/AlCgfrfzRe3e3+NvmefAdKQhRYpxS4u6clblBoDdzzvHi8fmxKRzvMxPY/1WZWzomPZww0Anow==", - "dev": true, - "hasInstallScript": true, - "dependencies": { - "chalk": "^4.0.0", - "ci-info": "^2.0.0", - "compare-versions": "^3.6.0", - "cosmiconfig": "^7.0.0", - "find-versions": "^4.0.0", - "opencollective-postinstall": "^2.0.2", - "pkg-dir": "^5.0.0", - "please-upgrade-node": "^3.2.0", - "slash": "^3.0.0", - "which-pm-runs": "^1.0.0" - }, - "bin": { - "husky-run": "bin/run.js", - "husky-upgrade": "lib/upgrader/bin.js" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/husky" - } - }, - "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/is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", - "dev": true - }, - "node_modules/js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true - }, - "node_modules/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/lines-and-columns": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.1.6.tgz", - "integrity": "sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA=", - "dev": true - }, - "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/opencollective-postinstall": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/opencollective-postinstall/-/opencollective-postinstall-2.0.3.tgz", - "integrity": "sha512-8AV/sCtuzUeTo8gQK5qDZzARrulB3egtLzFgteqB2tcT4Mw7B8Kt7JcDHmltjz6FOAHsvTevk70gZEbhM4ZS9Q==", - "dev": true, - "bin": { - "opencollective-postinstall": "index.js" - } - }, - "node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "dependencies": { - "yocto-queue": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, - "dependencies": { - "p-limit": "^3.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/parent-module": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", - "dev": true, - "dependencies": { - "callsites": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/parse-json": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", - "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.0.0", - "error-ex": "^1.3.1", - "json-parse-even-better-errors": "^2.3.0", - "lines-and-columns": "^1.1.6" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/pkg-dir": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-5.0.0.tgz", - "integrity": "sha512-NPE8TDbzl/3YQYY7CSS228s3g2ollTFnc+Qi3tqmqJp9Vg2ovUpixcJEo2HJScN2Ez+kEaal6y70c0ehqJBJeA==", - "dev": true, - "dependencies": { - "find-up": "^5.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/please-upgrade-node": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/please-upgrade-node/-/please-upgrade-node-3.2.0.tgz", - "integrity": "sha512-gQR3WpIgNIKwBMVLkpMUeR3e1/E1y42bqDQZfql+kDeXd8COYfM8PQA4X6y7a8u9Ua9FHmsrrmirW2vHs45hWg==", - "dev": true, - "dependencies": { - "semver-compare": "^1.0.0" - } - }, - "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/semver-compare": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz", - "integrity": "sha1-De4hahyUGrN+nvsXiPavxf9VN/w=", - "dev": true - }, - "node_modules/semver-regex": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/semver-regex/-/semver-regex-3.1.3.tgz", - "integrity": "sha512-Aqi54Mk9uYTjVexLnR67rTyBusmwd04cLkHy9hNvk3+G3nT2Oyg7E0l4XVbOaNwIvQ3hHeYxGcyEy+mKreyBFQ==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/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/which-pm-runs": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/which-pm-runs/-/which-pm-runs-1.0.0.tgz", - "integrity": "sha1-Zws6+8VS4LVd9rd4DKdGFfI60cs=", - "dev": true - }, - "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, - "engines": { - "node": ">= 6" - } - }, - "node_modules/yocto-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - } - }, - "dependencies": { - "@babel/code-frame": { - "version": "7.15.8", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.15.8.tgz", - "integrity": "sha512-2IAnmn8zbvC/jKYhq5Ki9I+DwjlrtMPUCH/CpHvqI4dNnlwHwsxoIhlc8WcYY5LSYknXQtAlFYuHfqAFCvQ4Wg==", - "dev": true, - "requires": { - "@babel/highlight": "^7.14.5" - } - }, - "@babel/helper-validator-identifier": { - "version": "7.15.7", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.15.7.tgz", - "integrity": "sha512-K4JvCtQqad9OY2+yTU8w+E82ywk/fe+ELNlt1G8z3bVGlZfn/hOcQQsUhGhW/N+tb3fxK800wLtKOE/aM0m72w==", - "dev": true - }, - "@babel/highlight": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.14.5.tgz", - "integrity": "sha512-qf9u2WFWVV0MppaL877j2dBtQIDgmidgjGk5VIMw3OadXvYaXn66U1BFlH2t4+t3i+8PhedppRv+i40ABzd+gg==", - "dev": true, - "requires": { - "@babel/helper-validator-identifier": "^7.14.5", - "chalk": "^2.0.0", - "js-tokens": "^4.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "@types/parse-json": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz", - "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==", - "dev": true - }, - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "ci-info": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", - "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==", - "dev": true - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "compare-versions": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/compare-versions/-/compare-versions-3.6.0.tgz", - "integrity": "sha512-W6Af2Iw1z4CB7q4uU4hv646dW9GQuBM+YpC0UvUCWSD8w90SJjp+ujJuXaEMtAXBtSqGfMPuFOVn4/+FlaqfBA==", - "dev": true - }, - "cosmiconfig": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.0.1.tgz", - "integrity": "sha512-a1YWNUV2HwGimB7dU2s1wUMurNKjpx60HxBB6xUM8Re+2s1g1IIfJvFR0/iCF+XHdE0GMTKTuLR32UQff4TEyQ==", - "dev": true, - "requires": { - "@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" - } - }, - "error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "dev": true, - "requires": { - "is-arrayish": "^0.2.1" - } - }, - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", - "dev": true - }, - "find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, - "requires": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - } - }, - "find-versions": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/find-versions/-/find-versions-4.0.0.tgz", - "integrity": "sha512-wgpWy002tA+wgmO27buH/9KzyEOQnKsG/R0yrcjPT9BOFm0zRBVQbZ95nRGXWMywS8YR5knRbpohio0bcJABxQ==", - "dev": true, - "requires": { - "semver-regex": "^3.1.2" - } - }, - "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 - }, - "husky": { - "version": "4.3.8", - "resolved": "https://registry.npmjs.org/husky/-/husky-4.3.8.tgz", - "integrity": "sha512-LCqqsB0PzJQ/AlCgfrfzRe3e3+NvmefAdKQhRYpxS4u6clblBoDdzzvHi8fmxKRzvMxPY/1WZWzomPZww0Anow==", - "dev": true, - "requires": { - "chalk": "^4.0.0", - "ci-info": "^2.0.0", - "compare-versions": "^3.6.0", - "cosmiconfig": "^7.0.0", - "find-versions": "^4.0.0", - "opencollective-postinstall": "^2.0.2", - "pkg-dir": "^5.0.0", - "please-upgrade-node": "^3.2.0", - "slash": "^3.0.0", - "which-pm-runs": "^1.0.0" - } - }, - "import-fresh": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", - "dev": true, - "requires": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - } - }, - "is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", - "dev": true - }, - "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 - }, - "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 - }, - "lines-and-columns": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.1.6.tgz", - "integrity": "sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA=", - "dev": true - }, - "locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, - "requires": { - "p-locate": "^5.0.0" - } - }, - "opencollective-postinstall": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/opencollective-postinstall/-/opencollective-postinstall-2.0.3.tgz", - "integrity": "sha512-8AV/sCtuzUeTo8gQK5qDZzARrulB3egtLzFgteqB2tcT4Mw7B8Kt7JcDHmltjz6FOAHsvTevk70gZEbhM4ZS9Q==", - "dev": true - }, - "p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "requires": { - "yocto-queue": "^0.1.0" - } - }, - "p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, - "requires": { - "p-limit": "^3.0.2" - } - }, - "parent-module": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", - "dev": true, - "requires": { - "callsites": "^3.0.0" - } - }, - "parse-json": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", - "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.0.0", - "error-ex": "^1.3.1", - "json-parse-even-better-errors": "^2.3.0", - "lines-and-columns": "^1.1.6" - } - }, - "path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true - }, - "path-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 - }, - "pkg-dir": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-5.0.0.tgz", - "integrity": "sha512-NPE8TDbzl/3YQYY7CSS228s3g2ollTFnc+Qi3tqmqJp9Vg2ovUpixcJEo2HJScN2Ez+kEaal6y70c0ehqJBJeA==", - "dev": true, - "requires": { - "find-up": "^5.0.0" - } - }, - "please-upgrade-node": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/please-upgrade-node/-/please-upgrade-node-3.2.0.tgz", - "integrity": "sha512-gQR3WpIgNIKwBMVLkpMUeR3e1/E1y42bqDQZfql+kDeXd8COYfM8PQA4X6y7a8u9Ua9FHmsrrmirW2vHs45hWg==", - "dev": true, - "requires": { - "semver-compare": "^1.0.0" - } - }, - "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 - }, - "semver-compare": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz", - "integrity": "sha1-De4hahyUGrN+nvsXiPavxf9VN/w=", - "dev": true - }, - "semver-regex": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/semver-regex/-/semver-regex-3.1.3.tgz", - "integrity": "sha512-Aqi54Mk9uYTjVexLnR67rTyBusmwd04cLkHy9hNvk3+G3nT2Oyg7E0l4XVbOaNwIvQ3hHeYxGcyEy+mKreyBFQ==", - "dev": true - }, - "slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - }, - "which-pm-runs": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/which-pm-runs/-/which-pm-runs-1.0.0.tgz", - "integrity": "sha1-Zws6+8VS4LVd9rd4DKdGFfI60cs=", - "dev": true - }, - "yaml": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", - "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", - "dev": true - }, - "yocto-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", - "dev": true - } - } -} diff --git a/package.json b/package.json deleted file mode 100644 index 3914640..0000000 --- a/package.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "private": true, - "devDependencies": { - "husky": "^4.3.0" - } -} diff --git a/phpstan-package.neon b/phpstan-package.neon new file mode 100644 index 0000000..e69de29 diff --git a/phpstan.neon.dist b/phpstan.neon.dist new file mode 100644 index 0000000..a2205ac --- /dev/null +++ b/phpstan.neon.dist @@ -0,0 +1,61 @@ +includes: + - ./vendor/spaze/phpstan-disallowed-calls/disallowed-dangerous-calls.neon + - ./phpstan-package.neon + +parameters: + paths: + - src + + scanFiles: + + # Pest handles loading custom helpers only when running tests + # @see https://pestphp.com/docs/helpers#usage + - tests/Pest.php + + # The level 9 is the highest level + level: 5 + + ignoreErrors: + - '#PHPDoc tag @var#' + + - '#Unsafe usage of new static\(\)\.#' + + # Pest implicitly binds $this to the current test case + # @see https://pestphp.com/docs/underlying-test-case + - + message: '#^Undefined variable: \$this$#' + path: '*Test.php' + + # Pest custom expectations are dynamic and not conducive static analysis + # @see https://pestphp.com/docs/expectations#custom-expectations + - + message: '#Call to an undefined method Pest\\Expectation|Pest\\Support\\Extendable::#' + path: '*Test.php' + + # Pest allow pass any array for TestCall::with + - + message: '#Parameter \#\d ...\$data of method Pest\\PendingCalls\\TestCall::with(.*) array(.*)given#' + path: '*Test.php' + + # Ignore custom method for Faker\Generator + - + message: '#Call to an undefined method Faker\\Generator|Ensi\\TestFactories\\FakerProvider::#' + path: '*Factory.php' + + # Ignore transfer of UploadedFile in auto-generated lib + - + message: '#expects SplFileObject\|null, Illuminate\\Http\\UploadedFile given.#' + path: '*Action.php' + + excludePaths: + - ./*/*/FileToBeExcluded.php + + disallowedFunctionCalls: + - + function: 'dd()' + message: 'use some logger instead' + - + function: 'dump()' + message: 'use some logger instead' + + reportUnmatchedIgnoredErrors: false diff --git a/phpunit.xml b/phpunit.xml new file mode 100644 index 0000000..c2a4f58 --- /dev/null +++ b/phpunit.xml @@ -0,0 +1,20 @@ + + + + + tests + + + + + ./src + + + + + + diff --git a/phpunit.xml.dist b/phpunit.xml.dist deleted file mode 100644 index 01d6da8..0000000 --- a/phpunit.xml.dist +++ /dev/null @@ -1,39 +0,0 @@ - - - - - tests - - - - - ./src - - - - - - - - - - - \ No newline at end of file diff --git a/src/Commands/GenerateServer.php b/src/Commands/GenerateServer.php index 96118ed..89406d9 100644 --- a/src/Commands/GenerateServer.php +++ b/src/Commands/GenerateServer.php @@ -100,7 +100,7 @@ private function validateEntities(): bool $supportedEntities = array_keys($this->config['supported_entities'] ?? []); foreach ($this->enabledEntities as $entity) { if (!in_array($entity, $supportedEntities)) { - $this->error("Invalid entity \"$entity\", supported entities: [" . implode(', ', $supportedEntities) ."]"); + $this->error("Invalid entity \"$entity\", supported entities: [" . implode(', ', $supportedEntities) . "]"); return false; } diff --git a/src/Data/OpenApi3/OpenApi3Object.php b/src/Data/OpenApi3/OpenApi3Object.php index 3bc7693..511e965 100644 --- a/src/Data/OpenApi3/OpenApi3Object.php +++ b/src/Data/OpenApi3/OpenApi3Object.php @@ -21,7 +21,7 @@ public function fillFromStdObject(stdClass $object): void { if (std_object_has($object, 'properties')) { foreach (get_object_vars($object->properties) as $propertyName => $property) { - /** @var OpenApi3ObjectProperty $objectProperty */ + /** @var OpenApi3ObjectProperty|null $objectProperty */ $objectProperty = $this->properties->get($propertyName); if (!$objectProperty) { do_with_all_of($property, function (stdClass $p) use (&$objectProperty, $propertyName) { @@ -80,13 +80,10 @@ public function toLaravelValidationRules(array $options): array if ($enums) { throw_unless(isset($options['enums']['namespace']), EnumsNamespaceMissingException::class); - $enumStrings = []; + $enumStrings = ['use Illuminate\Validation\Rules\Enum;']; foreach ($enums as $enumClass => $value) { $enumStrings[] = 'use ' . $options['enums']['namespace'] . "{$enumClass};"; } - if ($enumStrings) { - $enumStrings[] = 'use Illuminate\Validation\Rules\Enum;'; - } sort($enumStrings); $enumsString = implode("\n", $enumStrings); } else { diff --git a/src/Data/OpenApi3/OpenApi3ObjectProperty.php b/src/Data/OpenApi3/OpenApi3ObjectProperty.php index 8967a5c..f41aa46 100644 --- a/src/Data/OpenApi3/OpenApi3ObjectProperty.php +++ b/src/Data/OpenApi3/OpenApi3ObjectProperty.php @@ -106,7 +106,7 @@ protected function getValidationsAndEnumsByTypeAndFormat(array $options, array & break; case OpenApi3PropertyFormatEnum::BINARY: - $validations[$name][] = "'". LaravelValidationRuleEnum::FILE->value . "'"; + $validations[$name][] = "'" . LaravelValidationRuleEnum::FILE->value . "'"; break; default: diff --git a/src/Enums/OpenApi3PropertyFormatEnum.php b/src/Enums/OpenApi3PropertyFormatEnum.php index 221366a..6f117f3 100644 --- a/src/Enums/OpenApi3PropertyFormatEnum.php +++ b/src/Enums/OpenApi3PropertyFormatEnum.php @@ -34,6 +34,7 @@ public function toLaravelValidationRule(): LaravelValidationRuleEnum OpenApi3PropertyFormatEnum::PHONE => LaravelValidationRuleEnum::PHONE, OpenApi3PropertyFormatEnum::URL => LaravelValidationRuleEnum::URL, OpenApi3PropertyFormatEnum::UUID => LaravelValidationRuleEnum::UUID, + default => throw new \Exception('Can\'t convert to Laravel validation rule.'), }; } } diff --git a/src/Enums/OpenApi3PropertyTypeEnum.php b/src/Enums/OpenApi3PropertyTypeEnum.php index daefc28..404aeae 100644 --- a/src/Enums/OpenApi3PropertyTypeEnum.php +++ b/src/Enums/OpenApi3PropertyTypeEnum.php @@ -14,11 +14,12 @@ enum OpenApi3PropertyTypeEnum: string public function toLaravelValidationRule(): LaravelValidationRuleEnum { return match ($this) { - OpenApi3PropertyTypeEnum::INTEGER => LaravelValidationRuleEnum::INTEGER, - OpenApi3PropertyTypeEnum::STRING => LaravelValidationRuleEnum::STRING, - OpenApi3PropertyTypeEnum::BOOLEAN => LaravelValidationRuleEnum::BOOLEAN, - OpenApi3PropertyTypeEnum::NUMBER => LaravelValidationRuleEnum::NUMERIC, - OpenApi3PropertyTypeEnum::ARRAY => LaravelValidationRuleEnum::ARRAY, + OpenApi3PropertyTypeEnum::INTEGER => LaravelValidationRuleEnum::INTEGER, + OpenApi3PropertyTypeEnum::STRING => LaravelValidationRuleEnum::STRING, + OpenApi3PropertyTypeEnum::BOOLEAN => LaravelValidationRuleEnum::BOOLEAN, + OpenApi3PropertyTypeEnum::NUMBER => LaravelValidationRuleEnum::NUMERIC, + OpenApi3PropertyTypeEnum::ARRAY => LaravelValidationRuleEnum::ARRAY, + default => throw new \Exception('Can\'t convert to Laravel validation rule.'), }; } } diff --git a/src/Generators/ControllersGenerator.php b/src/Generators/ControllersGenerator.php index 48a1b69..3be9cf1 100644 --- a/src/Generators/ControllersGenerator.php +++ b/src/Generators/ControllersGenerator.php @@ -64,7 +64,7 @@ private function extractControllers(SpecObjectInterface $specObject): array $requestNamespace = $this->getReplacedNamespace($handler->namespace, 'Controllers', 'Requests'); list($requestClassName, $requestNamespace) = $this->getActualClassNameAndNamespace($requestClassName, $requestNamespace); - $requestNamespace .= '\\' . ucfirst($requestClassName); + $requestNamespace .= '\\' . ucfirst($requestClassName); $controllers[$fqcn]['requestsNamespaces'][$requestNamespace] = $requestNamespace; } @@ -89,7 +89,7 @@ private function extractControllers(SpecObjectInterface $specObject): array private function extractPathParameters(stdClass $route): array { - $oasRoutePath = array_filter($route->parameters ?? [], fn (stdClass $param) => $param?->in === "path"); + $oasRoutePath = array_filter($route->parameters ?? [], fn (stdClass $param) => $param->in === "path"); return array_map(fn (stdClass $param) => [ 'name' => $param->name, diff --git a/src/Generators/EnumsGenerator.php b/src/Generators/EnumsGenerator.php index b09295b..4379498 100644 --- a/src/Generators/EnumsGenerator.php +++ b/src/Generators/EnumsGenerator.php @@ -40,9 +40,9 @@ public function generate(SpecObjectInterface $specObject): void } } - private function extractEnums(stdClass $openApiData): array + private function extractEnums(stdClass $openApiData): array { - $schemas = (array) $openApiData?->components?->schemas; + $schemas = (array) $openApiData->components?->schemas; return array_filter($schemas, fn ($schema) => !empty($schema->enum)); } diff --git a/src/Generators/PestTestsGenerator.php b/src/Generators/PestTestsGenerator.php index 7d69a52..fc0c25a 100644 --- a/src/Generators/PestTestsGenerator.php +++ b/src/Generators/PestTestsGenerator.php @@ -56,7 +56,7 @@ protected function convertRoutesToTestsString(array $routes, string $serversUrl, } $url = $serversUrl . $route['path']; - $testName = strtoupper($route['method']) . ' ' . $url. ' ' . $responseCode; + $testName = strtoupper($route['method']) . ' ' . $url . ' ' . $responseCode; $phpHttpMethod = $this->getPhpHttpTestMethod($route['method'], $route['responseContentType']); $testsFunctions[] = <<formatHandler($handler, $controllerNamespaces); $routesStrings .= "Route::{$method}('{$this->trimPath($path)}', {$handler})"; - $routesStrings .= $routeName ? "->name('{$routeName}')": ""; - $routesStrings .= $routeMiddleware ? "->middleware({$this->formatMiddleware($routeMiddleware)})": ""; - $routesStrings .= $routeWithoutMiddleware ? "->withoutMiddleware({$this->formatMiddleware($routeWithoutMiddleware)})": ""; + $routesStrings .= $routeName ? "->name('{$routeName}')" : ""; + $routesStrings .= $routeMiddleware ? "->middleware({$this->formatMiddleware($routeMiddleware)})" : ""; + $routesStrings .= $routeWithoutMiddleware ? "->withoutMiddleware({$this->formatMiddleware($routeWithoutMiddleware)})" : ""; $routesStrings .= ";\n"; } } diff --git a/src/Generators/TestsGenerator.php b/src/Generators/TestsGenerator.php index c479c4c..571d456 100644 --- a/src/Generators/TestsGenerator.php +++ b/src/Generators/TestsGenerator.php @@ -57,9 +57,6 @@ protected function constructTests(stdClass $openApiData, array $namespaceData): $className = str_replace("Controller", "", $handler->class) . "ComponentTest"; - if (!$className) { - continue; - } $firstResponse = null; if (isset($route->responses)) { @@ -69,7 +66,7 @@ protected function constructTests(stdClass $openApiData, array $namespaceData): continue; } - $testFqcn = $handler->namespace . "\\". $className; + $testFqcn = $handler->namespace . "\\" . $className; if (!isset($tests[$testFqcn])) { $tests[$testFqcn] = [ 'className' => $className, diff --git a/src/LaravelOpenApiServerGeneratorServiceProvider.php b/src/LaravelOpenApiServerGeneratorServiceProvider.php index e395225..4762450 100644 --- a/src/LaravelOpenApiServerGeneratorServiceProvider.php +++ b/src/LaravelOpenApiServerGeneratorServiceProvider.php @@ -10,12 +10,9 @@ class LaravelOpenApiServerGeneratorServiceProvider extends ServiceProvider { - const CONFIG_FILE_NAME = 'openapi-server-generator.php'; + public const CONFIG_FILE_NAME = 'openapi-server-generator.php'; - /** - * @return void - */ - public function register() + public function register(): void { $this->mergeConfigFrom( __DIR__ . '/../config/' . self::CONFIG_FILE_NAME, @@ -35,10 +32,7 @@ public function register() }); } - /** - * @return void - */ - public function boot() + public function boot(): void { $this->publishes([ __DIR__ . '/../config/' . self::CONFIG_FILE_NAME => config_path(self::CONFIG_FILE_NAME), diff --git a/src/Utils/PSR4PathConverter.php b/src/Utils/PSR4PathConverter.php index 11aba1f..6787e5e 100644 --- a/src/Utils/PSR4PathConverter.php +++ b/src/Utils/PSR4PathConverter.php @@ -13,7 +13,7 @@ public function __construct(private array $mappings = []) public function addMappings(array $mappings): static { foreach ($mappings as $namespace => $path) { - $this->mappings[$namespace] = $path; + $this->mappings[$namespace] = $path; } return $this; @@ -33,6 +33,6 @@ public function namespaceToPath(?string $namespace): string } } - throw new InvalidArgumentException("Namespace $namespace is unknown, supported namespaces must start with one of [". implode(array_keys($this->mappings)). "]"); + throw new InvalidArgumentException("Namespace $namespace is unknown, supported namespaces must start with one of [" . implode(array_keys($this->mappings)) . "]"); } } diff --git a/tests/ClassParserTest.php b/tests/ClassParserTest.php index 48996cb..211b251 100644 --- a/tests/ClassParserTest.php +++ b/tests/ClassParserTest.php @@ -136,12 +136,12 @@ 'LaravelExists_1_Controller', "\n public function test() {}\n", [ - "App\Http\ApiV1\Support\Resources\EmptyResource" => "App\Http\ApiV1\Support\Resources\EmptyResource", + "App\Http\ApiV1\Support\Resources\EmptyResource" => "App\Http\ApiV1\Support\Resources\EmptyResource", ], [ - "App\Http\ApiV1\Support\Resources\EmptyResource" => "App\Http\ApiV1\Support\Resources\EmptyResource", - "Illuminate\Contracts\Support\Responsable" => "Illuminate\Contracts\Support\Responsable", - "Illuminate\Http\Request" => "Illuminate\Http\Request", + "App\Http\ApiV1\Support\Resources\EmptyResource" => "App\Http\ApiV1\Support\Resources\EmptyResource", + "Illuminate\Contracts\Support\Responsable" => "Illuminate\Contracts\Support\Responsable", + "Illuminate\Http\Request" => "Illuminate\Http\Request", ], ], [ @@ -150,8 +150,8 @@ "", [], [ - "Illuminate\Contracts\Support\Responsable" => "Illuminate\Contracts\Support\Responsable", - "Illuminate\Http\Request" => "Illuminate\Http\Request", + "Illuminate\Contracts\Support\Responsable" => "Illuminate\Contracts\Support\Responsable", + "Illuminate\Http\Request" => "Illuminate\Http\Request", ], ], [LaravelEmptyController::class, 'LaravelEmpty_1_Controller'], diff --git a/tests/GenerateServerTest.php b/tests/GenerateServerTest.php index 15cd4a6..1f9e3e3 100644 --- a/tests/GenerateServerTest.php +++ b/tests/GenerateServerTest.php @@ -4,6 +4,7 @@ use Ensi\LaravelOpenApiServerGenerator\Tests\TestCase; use Illuminate\Filesystem\Filesystem; use Illuminate\Support\Facades\Config; + use function Pest\Laravel\artisan; use function PHPUnit\Framework\assertEquals; use function PHPUnit\Framework\assertEqualsCanonicalizing; @@ -164,10 +165,10 @@ artisan(GenerateServer::class, ['-e' => 'routes']); assertStringContainsString( - "use App\Http\Controllers\Controller11;\n". - "use App\Http\Controllers\Controller2;\n". + "use App\Http\Controllers\Controller11;\n" . + "use App\Http\Controllers\Controller2;\n" . "use App\Http\Controllers\Foo\TestController;\n" . - "use App\Http\Controllers\FooItemsController;\n". + "use App\Http\Controllers\FooItemsController;\n" . "use App\Http\Controllers\FoosController;\n", $routes ); diff --git a/tests/LaravelValidationRulesRequestTest.php b/tests/LaravelValidationRulesRequestTest.php index 7b00b00..768d240 100644 --- a/tests/LaravelValidationRulesRequestTest.php +++ b/tests/LaravelValidationRulesRequestTest.php @@ -4,6 +4,7 @@ use Ensi\LaravelOpenApiServerGenerator\Tests\TestCase; use Illuminate\Filesystem\Filesystem; use Illuminate\Support\Facades\Config; + use function Pest\Laravel\artisan; use function PHPUnit\Framework\assertEquals; diff --git a/tests/PSR4PathConverterTest.php b/tests/PSR4PathConverterTest.php index bb7ac83..934a20e 100644 --- a/tests/PSR4PathConverterTest.php +++ b/tests/PSR4PathConverterTest.php @@ -3,7 +3,7 @@ use Ensi\LaravelOpenApiServerGenerator\Utils\PSR4PathConverter; it('throws InvalidArgumentException for unregistred namespaces', function () { - $converter = new PSR4PathConverter(["App\\" =>"/var/www/acme/app"]); + $converter = new PSR4PathConverter(["App\\" => "/var/www/acme/app"]); $converter->namespaceToPath("Foo\\Bar"); })->throws(InvalidArgumentException::class); diff --git a/tests/Pest.php b/tests/Pest.php index 9cbf1e9..92d565b 100644 --- a/tests/Pest.php +++ b/tests/Pest.php @@ -2,4 +2,47 @@ use Ensi\LaravelOpenApiServerGenerator\Tests\TestCase; +/* +|-------------------------------------------------------------------------- +| Test Case +|-------------------------------------------------------------------------- +| +| The closure you provide to your test functions is always bound to a specific PHPUnit test +| case class. By default, that class is "PHPUnit\Framework\TestCase". Of course, you may +| need to change it using the "uses()" function to bind a different classes or traits. +| +*/ + uses(TestCase::class)->in(__DIR__); + + +/* +|-------------------------------------------------------------------------- +| Expectations +|-------------------------------------------------------------------------- +| +| When you're writing tests, you often need to check that values meet certain conditions. The +| "expect()" function gives you access to a set of "expectations" methods that you can use +| to assert different things. Of course, you may extend the Expectation API at any time. +| +*/ + +//expect()->extend('toBeOne', function () { +// return $this->toBe(1); +//}); + +/* +|-------------------------------------------------------------------------- +| Functions +|-------------------------------------------------------------------------- +| +| While Pest is very powerful out-of-the-box, you may have some testing code specific to your +| project that you don't want to repeat in every file. Here you can also expose helpers as +| global functions to help you to reduce the number of lines of code in your test files. +| +*/ + +//function something() +//{ +// // .. +//} diff --git a/tests/ResourceGenerationTest.php b/tests/ResourceGenerationTest.php index dc58283..2ee307d 100644 --- a/tests/ResourceGenerationTest.php +++ b/tests/ResourceGenerationTest.php @@ -4,6 +4,7 @@ use Ensi\LaravelOpenApiServerGenerator\Tests\TestCase; use Illuminate\Filesystem\Filesystem; use Illuminate\Support\Facades\Config; + use function Pest\Laravel\artisan; use function PHPUnit\Framework\assertEqualsCanonicalizing; diff --git a/tests/TestCase.php b/tests/TestCase.php index 46b2161..2e4eb5c 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -8,19 +8,20 @@ class TestCase extends Orchestra { - protected function setUp(): void - { - parent::setUp(); - $this->mockClassParserGenerator(); - } - - protected function getPackageProviders($app) + protected function getPackageProviders($app): array { return [ LaravelOpenApiServerGeneratorServiceProvider::class, ]; } + protected function setUp(): void + { + parent::setUp(); + + $this->mockClassParserGenerator(); + } + public function makeFilePath(string $path): string { return str_replace('/', DIRECTORY_SEPARATOR, $path); @@ -43,9 +44,4 @@ protected function forgetMockClassParserGenerator(): void { $this->forgetMock(ClassParser::class); } - - public function getEnvironmentSetUp($app) - { - config()->set('database.default', 'testing'); - } }