diff --git a/.docker/dbtest.php b/.docker/dbtest.php new file mode 100755 index 000000000..a54ccb4ca --- /dev/null +++ b/.docker/dbtest.php @@ -0,0 +1,55 @@ + \PDO::ERRMODE_EXCEPTION ]);"; +# echo "*"; + +try { + $pdo = new \PDO("mysql:host=$DB_HOST;dbname=$DB_BASE;port=$DB_PORT", "$DB_USER", "$DB_PASS", [ + \PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION + ]); +} catch(\Exception $ex) { + switch ($ex->getCode()) { + // we can immediately stop startup here and show the error message + case 1045: + echo 'Access denied (1045)'; + die(1); + // we can immediately stop startup here and show the error message + case 1049: + echo 'Unknown database (1049)'; + die(2); + // a lot of errors share the same meaningless error code zero + case 0: + // this error includes the database name, so we can only search for the static part of the error message + if (stripos($ex->getMessage(), 'SQLSTATE[HY000] [1049] Unknown database') !== false) { + echo 'Unknown database (0-1049)'; + die(3); + } + switch ($ex->getMessage()) { + // eg. no response (fw) - the startup script should retry it a couple of times + case 'SQLSTATE[HY000] [2002] Operation timed out': + echo 'Operation timed out (0-2002)'; + die(4); + // special case "localhost" with a stopped db server (should not happen in docker compose setup) + case 'SQLSTATE[HY000] [2002] No such file or directory': + echo 'Connection could not be established (0-2002)'; + die(5); + // using IP with stopped db server - the startup script should retry it a couple of times + case 'SQLSTATE[HY000] [2002] Connection refused': + echo 'Connection refused (0-2002)'; + die(5); + } + echo $ex->getMessage() . " (0)"; + die(7); + default: + // unknown error + echo $ex->getMessage() . " (?)"; + die(10); + } +} diff --git a/.docker/docker-compose.yml b/.docker/docker-compose.yml new file mode 100644 index 000000000..6294304e4 --- /dev/null +++ b/.docker/docker-compose.yml @@ -0,0 +1,62 @@ +version: '3.5' +services: + + sqldb: + image: mysql:5.7 + environment: + - MYSQL_DATABASE=arcv + - MYSQL_USER=arcvuser + - MYSQL_PASSWORD=arcvpassword + - MYSQL_ROOT_PASSWORD=changemeplease + command: --default-storage-engine innodb + restart: unless-stopped + healthcheck: + test: mysqladmin -p$$MYSQL_ROOT_PASSWORD ping -h localhost + interval: 20s + start_period: 10s + timeout: 10s + retries: 3 + + web: + image: nginx + ports: + - 8080:80 + volumes: + - ./nginx_default.conf:/etc/nginx/conf.d/default.conf + - ../:/opt/project:ro + + service: + image: arc-service:dev + build: + context: .. + target: dev + environment: + - APP_URL=http://arcv-service.test + - ARC_MARKET_URL=http://arcv-market.test + - ARC_STORE_DOMAIN=arcv-store.test + - DB_CONNECTION=mysql + - DB_HOST=sqldb + - DB_PORT=3306 + - DB_DATABASE=arcv + - DB_USERNAME=arcvuser + - DB_PASSWORD=arcvpassword + - LOG_CHANNEL=stderr + - MAIL_HOST=mailer + - MAIL_PORT=1025 + - SESSION_SECURE_COOKIE=false + volumes: + # this seems to overwrite the .env file that passport HAS to have as a file + - ..:/opt/project + extra_hosts: + - "host.docker.internal:host-gateway" + - "arcv-service.test:host-gateway" + - "arcv-store.test:host-gateway" + - "arcv-market.test:host-gateway" + + mailer: + image: schickling/mailcatcher + ports: + - "${MAILER_ADMIN_PORT:-2080}:1080" + +volumes: + service_public: \ No newline at end of file diff --git a/.docker/entry-point.sh b/.docker/entry-point.sh new file mode 100755 index 000000000..723edf7ef --- /dev/null +++ b/.docker/entry-point.sh @@ -0,0 +1,86 @@ +#!/bin/bash + +function checkDatabase() { + echo "Wait for MySQL DB connection ..." + echo -n "Checking DB" + until php /dbtest.php "$DB_HOST" "$DB_DATABASE" "$DB_PORT" "$DB_USERNAME" "$DB_PASSWORD"; do + echo -n "." + sleep 3 + done + echo " ✅ Connection established" +} + +function handleStartup() { + # in production we will have a .env mounted into the container, this will have (at least) a + # APP_KEY, if we don't have a .env we will create one + if [ ! -e /opt/project/.env ]; then + if [ "$APP_ENV" == "production" ]; then + echo "No .env file present." + echo "Your are running a prod environment version but there is no .env file present" + echo "You need to mount one into this container or the system cannot proceed." + exit 1 + else + touch .env + fi + fi + + grep APP_KEY .env + # shellcheck disable=SC2181 + if [ "$?" != 0 ]; then + echo "APP_KEY=''" > .env + php /opt/project/artisan key:generate + fi + + # These are idempotent, run them anyway + php /opt/project/artisan migrate + if [ "$APP_ENV" == "local" ] || [ "$APP_ENV" == "dev" ] || [ "$APP_ENV" == "development" ] ; then + # check the DB, if there are no vouchers install fixtures + voucher_count=$(/opt/project/artisan tinker --execute='print(App\Voucher::all()->count())') + if [ "$voucher_count" == "0" ]; then + php /opt/project/artisan migrate:refresh --seed --force + fi + fi + + php /passport-install.php + chmod 644 /opt/project/storage/oauth-p* + + if [ -e /docker-entrypoint-initdb.d ]; then + for filename in /docker-entrypoint-init.d/*; do + if [ "${filename##*.}" == "sh" ]; then + # shellcheck disable=SC1090 + source /docker-entrypoint-initdb.d/"$filename" + fi + done + fi + yarn production +} + +checkDatabase +handleStartup + +if [ -n "$RUN_AS" ]; then + GROUP_ID=${RUN_AS#*:} + USER_ID=${RUN_AS%:*} # drops substring from last occurrence of `SubStr` to end of string + + GROUP_NAME=$(id -ng "$GROUP_ID") + if [ -z "$GROUP_NAME" ]; then + addgroup --gid "$GROUP_ID" arcuser + GROUP_NAME=arcuser + fi + + USER_NAME=$(id -n "$USER_ID") + if [ -z "$USER_NAME" ]; then + adduser -G "$GROUP_NAME" -u "$USER_ID" arcuser + USER_NAME=arcuser + fi + sed -i "s/user = www-data/user = $USER_NAME/g" /usr/local/etc/php-fpm.d/www.conf + sed -i "s/group = www-data/group = $GROUP_NAME/g" /usr/local/etc/php-fpm.d/www.conf + + chown -R $USER_NAME:$GROUP_NAME /opt/project/storage +fi + +env | sort + +exec php-fpm + +exit diff --git a/.docker/nginx_default.conf b/.docker/nginx_default.conf new file mode 100644 index 000000000..adb0b80c8 --- /dev/null +++ b/.docker/nginx_default.conf @@ -0,0 +1,60 @@ +server { + listen 80; + root /usr/share/nginx/html; + index index.html; + + server_name _; + + location / { + try_files $uri /index.html; + } + + location /ping { + access_log off; + add_header 'Content-Type' 'application/json'; + return 200 '{"status":"UP"}'; + } +} + +server { + listen 80; + server_name arcv-service.test arcv-store.test; + root /opt/project/public; + + index index.php; + + location / { + try_files $uri $uri/ /index.php?$query_string; + } + + location /ping { + access_log off; + add_header 'Content-Type' 'application/json'; + return 200 '{"status":"UP"}'; + } + + location ~ \.php$ { + try_files $uri =404; + fastcgi_pass service:9000; + fastcgi_index index.php; + fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; + include fastcgi_params; + } + + ssl_protocols TLSv1.2; + ssl_prefer_server_ciphers on; + ssl_dhparam /etc/ssl/certs/dhparam.pem; + ssl_ciphers ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384; + ssl_ecdh_curve secp384r1; # Requires nginx >= 1.1.0 + ssl_session_timeout 10m; + ssl_session_cache shared:SSL:10m; + ssl_session_tickets off; # Requires nginx >= 1.5.9 + # ssl_stapling on; # Requires nginx >= 1.3.7 + # ssl_stapling_verify on; # Requires nginx => 1.3.7 + resolver 8.8.8.8 8.8.4.4 valid=300s; + resolver_timeout 5s; + add_header X-Frame-Options DENY; + add_header X-Content-Type-Options nosniff; + add_header X-XSS-Protection "1; mode=block"; +} + diff --git a/.docker/passport-install.php b/.docker/passport-install.php new file mode 100644 index 000000000..182f217b3 --- /dev/null +++ b/.docker/passport-install.php @@ -0,0 +1,40 @@ + /opt/project/current_hash +WORKDIR /opt/project + +FROM composer:${COMPOSER_VER} AS composer + + +FROM php:${PHP_VER}-fpm-alpine AS fpm-php-ext-base +RUN apk add --no-cache \ + # build-tools + autoconf \ + dpkg \ + dpkg-dev \ + file \ + g++ \ + gcc \ + icu-dev \ + libatomic \ + libc-dev \ + libgomp \ + libmagic \ + linux-headers \ + m4 \ + make \ + mpc1 \ + mpfr4 \ + musl-dev \ + perl \ + re2c \ + # gd + freetype-dev \ + libpng-dev \ + # icu + icu-dev \ + icu-data-full \ + # ldap + openldap-dev \ + libldap \ + # zip + libzip-dev \ + # xsl + libxslt-dev + +FROM fpm-php-ext-base AS php-ext-gd +RUN docker-php-ext-configure gd \ + --with-freetype && \ + docker-php-ext-install -j$(nproc) gd + +FROM fpm-php-ext-base AS php-ext-intl +RUN docker-php-ext-install -j$(nproc) intl + +FROM fpm-php-ext-base AS php-ext-pdo_mysql +RUN docker-php-ext-install -j$(nproc) pdo_mysql + +FROM fpm-php-ext-base AS php-ext-zip +RUN docker-php-ext-install -j$(nproc) zip + +FROM fpm-php-ext-base AS php-ext-xsl +RUN docker-php-ext-install -j$(nproc) xsl + +FROM fpm-php-ext-base AS php-ext-opcache +RUN docker-php-ext-install -j$(nproc) opcache + +FROM fpm-php-ext-base AS php-ext-xdebug +RUN apk add --no-cache $PHPIZE_DEPS \ + && pecl install xdebug \ + && docker-php-ext-enable xdebug + +FROM php:${PHP_VER}-fpm-alpine AS fpm-base +ARG BRANCH +ARG TIMEZONE +RUN apk add --no-cache \ + bash \ + coreutils \ + fcgi \ + freetype \ + git \ + haveged \ + icu \ + icu-data-full \ + libldap \ + libpng \ + libxslt-dev \ + libzip \ + nodejs \ + npm \ + tzdata && \ + touch /use_fpm && \ + npm -g i yarn +EXPOSE 9000 +HEALTHCHECK --interval=60s --timeout=10s --retries=3 \ + CMD \ + SCRIPT_NAME=/ping \ + SCRIPT_FILENAME=/ping \ + REQUEST_METHOD=GET \ + cgi-fcgi -bind -connect 127.0.0.1:9000 || exit 1 + + +FROM fpm-base AS base +WORKDIR /opt/project +ARG BRANCH +ARG TIMEZONE +LABEL maintainer="tobias@neontribe.co.uk" +LABEL licence="proprietary" + +ENV BRANCH=${BRANCH} +ENV TIMEZONE=${TIMEZONE} +RUN ln -snf /usr/share/zoneinfo/${TIMEZONE} /etc/localtime && echo ${TIMEZONE} > /etc/timezone && \ + # make composer home dir + mkdir /composer && \ + chown -R www-data:www-data /composer +COPY ./.docker/entry-point.sh /entry-point.sh +COPY ./.docker/dbtest.php /dbtest.php +COPY ./.docker/passport-install.php /passport-install.php +COPY --from=composer /usr/bin/composer /usr/bin/composer +COPY --from=php-ext-xsl /usr/local/etc/php/conf.d/docker-php-ext-xsl.ini /usr/local/etc/php/conf.d/docker-php-ext-xsl.ini +COPY --from=php-ext-xsl /usr/local/lib/php/extensions/no-debug-non-zts-20210902/xsl.so /usr/local/lib/php/extensions/no-debug-non-zts-20210902/xsl.so +COPY --from=php-ext-pdo_mysql /usr/local/etc/php/conf.d/docker-php-ext-pdo_mysql.ini /usr/local/etc/php/conf.d/docker-php-ext-pdo_mysql.ini +COPY --from=php-ext-pdo_mysql /usr/local/lib/php/extensions/no-debug-non-zts-20210902/pdo_mysql.so /usr/local/lib/php/extensions/no-debug-non-zts-20210902/pdo_mysql.so +COPY --from=php-ext-zip /usr/local/etc/php/conf.d/docker-php-ext-zip.ini /usr/local/etc/php/conf.d/docker-php-ext-zip.ini +COPY --from=php-ext-zip /usr/local/lib/php/extensions/no-debug-non-zts-20210902/zip.so /usr/local/lib/php/extensions/no-debug-non-zts-20210902/zip.so +COPY --from=php-ext-gd /usr/local/etc/php/conf.d/docker-php-ext-gd.ini /usr/local/etc/php/conf.d/docker-php-ext-gd.ini +COPY --from=php-ext-gd /usr/local/lib/php/extensions/no-debug-non-zts-20210902/gd.so /usr/local/lib/php/extensions/no-debug-non-zts-20210902/gd.so +COPY --from=php-ext-intl /usr/local/etc/php/conf.d/docker-php-ext-intl.ini /usr/local/etc/php/conf.d/docker-php-ext-intl.ini +COPY --from=php-ext-intl /usr/local/lib/php/extensions/no-debug-non-zts-20210902/intl.so /usr/local/lib/php/extensions/no-debug-non-zts-20210902/intl.so +COPY --from=php-ext-opcache /usr/local/etc/php/conf.d/docker-php-ext-opcache.ini /usr/local/etc/php/conf.d/docker-php-ext-opcache.ini +ENV LOG_CHANNEL=stderr +ENV DATABASE_URL=sqlite:///%kernel.project_dir%/storage/data/db.sqlite +ENV COMPOSER_MEMORY_LIMIT=-1 +ENV COMPOSER_ALLOW_SUPERUSER=1 +ENV APP_NAME=ARCVService +ENV APP_ENV=local +ENV APP_VER=${BRANCH} +ENV APP_DEBUG=true +ENV APP_LOG_LEVEL=debug +ENV APP_URL=http://localhost:8080 +ENV APP_TIMEZONE=Europe/London +ENV APP_SEEDS='Dev' +ENV ARC_MARKET_URL=https://voucher-staging.alexandrarose.org.uk +ENV ARC_MVL_FILENAME=MVLReport.zip +ENV ARC_MVL_DISK=enc +ENV ARC_SCHOOL_MONTH=9 +ENV ARC_SCOTTISH_SCHOOL_MONTH=8 +ENV ARC_SERVICE_DOMAIN=arcv-service.test +ENV ARC_STORE_DOMAIN=arcv-store.test +ENV ARC_STORE_BUNDLE_MAX_VOUCHER_APPEND=100 +ENV ARC_FIRST_DELIVERY_DATE=2019-09-26 +ENV DB_CONNECTION=mysql +ENV DB_HOST=127.0.0.1 +ENV DB_PORT=3306 +ENV DB_DATABASE=homestead +ENV DB_USERNAME=homestead +ENV DB_PASSWORD=secret +ENV BROADCAST_DRIVER=log +ENV CACHE_DRIVER=file +ENV SESSION_DRIVER=file +ENV QUEUE_DRIVER=database +ENV SESSION_SECURE_COOKIE=false +ENV MAIL_MAILER=log +ENV MAIL_HOST=smtp.mailtrap.io +ENV MAIL_PORT=2525 +ENV MAIL_USERNAME=null +ENV MAIL_PASSWORD=null +ENV MAIL_ENCRYPTION=null +ENV MAIL_FROM_ADDRESS=from@example.com +ENV MAIL_FROM_NAME='Mailer Name' +ENV MAIL_TO_ADMIN_ADDRESS=to@example.com +ENV MAIL_TO_ADMIN_NAME='Admin Name' +ENV MAIL_TO_DEVELOPER_TEAM=arc@neontribe.co.uk +ENV MAIL_TO_DEVELOPER_NAME='User Support' +ENV RUN_AS="" +ENV PATH=$PATH:/opt/project/node_modules/.bin +VOLUME [ "/opt/project/storage" ] +ENTRYPOINT /entry-point.sh + +# developement build +FROM base AS dev +# copy kimai develop source +COPY --from=git-dev --chown=www-data:www-data /opt/project /opt/project +COPY ./.docker/xdebug.ini /usr/local/etc/php/conf.d/xdebug.ini +COPY --from=php-ext-xdebug /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini +COPY --from=php-ext-xdebug /usr/local/lib/php/extensions/no-debug-non-zts-20210902/xdebug.so /usr/local/lib/php/extensions/no-debug-non-zts-20210902/xdebug.so +RUN \ + export COMPOSER_HOME=/composer && \ + composer --no-ansi install --working-dir=/opt/project --optimize-autoloader && \ + composer --no-ansi clearcache && \ + cp /usr/local/etc/php/php.ini-development /usr/local/etc/php/php.ini && \ + chown -R www-data:www-data /opt/project /usr/local/etc/php/php.ini && \ + chown -R www-data:www-data /opt/project /usr/local/etc/php/php.ini && \ + echo "error_reporting=E_ALL" > /usr/local/etc/php/conf.d/error_reporting.ini && \ + yarn +ENV APP_ENV=dev +ENV memory_limit=256M + +# production build +FROM base AS prod +COPY --from=git-dev --chown=www-data:www-data /opt/project /opt/project +RUN export COMPOSER_HOME=/composer +RUN composer --no-ansi install --working-dir=/opt/project --no-dev --optimize-autoloader +RUN composer --no-ansi clearcache +RUN \ + cp /usr/local/etc/php/php.ini-production /usr/local/etc/php/php.ini && \ + sed -i "s/expose_php = On/expose_php = Off/g" /usr/local/etc/php/php.ini && \ + sed -i "s/;opcache.enable=1/opcache.enable=1/g" /usr/local/etc/php/php.ini && \ + sed -i "s/;opcache.memory_consumption=128/opcache.memory_consumption=256/g" /usr/local/etc/php/php.ini && \ + sed -i "s/;opcache.interned_strings_buffer=8/opcache.interned_strings_buffer=24/g" /usr/local/etc/php/php.ini && \ + sed -i "s/;opcache.max_accelerated_files=10000/opcache.max_accelerated_files=100000/g" /usr/local/etc/php/php.ini && \ + sed -i "s/opcache.validate_timestamps=1/opcache.validate_timestamps=0/g" /usr/local/etc/php/php.ini && \ + sed -i "s/session.gc_maxlifetime = 1440/session.gc_maxlifetime = 604800/g" /usr/local/etc/php/php.ini && \ + chown -R www-data:www-data /opt/project /usr/local/etc/php/php.ini && \ + yarn +ENV APP_DEBUG=false +ENV APP_ENV=prod +ENV SESSION_SECURE_COOKIE=true + +# docker build -t 192.168.21.97:5000/arcvouchers/service:prod . +# docker build -t 192.168.21.97:5000/arcvouchers/service:develop --target=dev . + +# docker push 192.168.21.97:5000/arcvouchers/service:prod +# docker push 192.168.21.97:5000/arcvouchers/service:develop diff --git a/Makefile b/Makefile deleted file mode 100644 index f1c108596..000000000 --- a/Makefile +++ /dev/null @@ -1,24 +0,0 @@ -NAME = dockerhost.neontribe.net:5000/arc -BRANCH = $(shell git rev-parse --abbrev-ref HEAD) -VERSION = $(subst /,_,$(BRANCH)) - -test: - env NAME=$(NAME) VERSION=$(VERSION) bats .docker/tests.bats - -build: - docker build -t $(NAME):$(VERSION) -f .docker/Dockerfile --rm . - -build-nocache: - docker build -t $(NAME):$(VERSION) -f .docker/Dockerfile --rm --no-cache . - -tag-latest: - docker tag $(NAME):$(VERSION) $(NAME):latest - -push: - docker push $(NAME):$(VERSION) - -release: build test tag-latest push - -info: - @echo Branch is $(BRANCH) - @echo Version is $(VERSION) diff --git a/README.md b/README.md index 88f138ad3..9d8a5cd36 100644 --- a/README.md +++ b/README.md @@ -3,6 +3,10 @@ ## About ARC Voucher Service/API ARCV Service is the service portal and API for ARCV Market. +## Docker and containers + +The service, market and store can be deployed, run locally for training/testing or development without any additional dependencies. Docker instructions are in the [infrastructure repo](https://github.com/neontribe/ARCVInfra/tree/main/docker/README.md) + ## Installation of Development instance 1. Clone the repo @@ -32,7 +36,7 @@ Use [semver](https://semver.org/) for versioning. Each sprint is considered a mi * Raise a PR into develop * Add a link to the PR into the Trello card * Wait for at least one approval on the PR - * Merge and delete branch + * Merge into develop and delete branch ### Create a Release candidate @@ -43,8 +47,9 @@ Use [semver](https://semver.org/) for versioning. Each sprint is considered a mi ### Creating a Release * Merge `develop` into `main` - * Tag main with a release, e.g. `git checkout main && git tag v1.16.0` - * Push the tag, `git push --tags` + * Create and tag a release + * Release to staging + * Test * Release to live ### Hotfix @@ -93,7 +98,7 @@ It also requires PHP's `zip` extension installed and enabled. - Service styling is in `resources/assets/sass/app.scss` - When amending the styles in development, switching to a new branch or pulling code, run `yarn watch` to watch for changes - Service is compiled from Sass with `yarn prod` -- +- #### Store - Store styling is in `public/store/css/main.css` diff --git a/app/Console/Commands/CreateMasterVoucherLogReport.php b/app/Console/Commands/CreateMasterVoucherLogReport.php index 5ad847baa..201d629c1 100644 --- a/app/Console/Commands/CreateMasterVoucherLogReport.php +++ b/app/Console/Commands/CreateMasterVoucherLogReport.php @@ -90,7 +90,7 @@ class CreateMasterVoucherLogReport extends Command private $zaOutput; // Excel can't deal with large CSVs - public const ROW_LIMIT = 900000; + const ROW_LIMIT = 900000; /** * The report's query template @@ -204,17 +204,11 @@ public function __construct() /** * @return void */ - public function initSettings(): void + public function initSettings() : void { $thisYearsApril = Carbon::parse('april')->startOfMonth(); - // $years = ($thisYearsApril->isPast()) ? 2 : 1; - // $this->cutOffDate = $thisYearsApril->subYearsNoOverflow($years)->format('Y-m-d'); - if ($thisYearsApril->isFuture()) { - $this->cutOffDate = $thisYearsApril->subYearsNoOverflow(1)->format('Y-m-d'); - } else { - $this->cutOffDate = $thisYearsApril->format('Y-m-d'); - } - + $years = ($thisYearsApril->isPast()) ? 2 : 1; + $this->cutOffDate = $thisYearsApril->subYearsNoOverflow($years)->format('Y-m-d'); // Set the disk $this->disk = ($this->option('plain')) @@ -322,7 +316,7 @@ public function handle() * * @return bool */ - public function warnUser(): bool + public function warnUser() : bool { $this->info('WARNING: This command will run a long, blocking query that will interrupt normal service use.'); return $this->confirm('Do you wish to continue?'); @@ -351,7 +345,7 @@ private function execQuery(int $limit, int $offset): bool|array * @param String $csv * @return bool */ - public function writeOutput(string $name, string $csv): bool + public function writeOutput(string $name, string $csv) : bool { try { $filename = sprintf("%s.csv", preg_replace('/\s+/', '_', $name)); @@ -410,31 +404,31 @@ public function containsOnlyNull(array $array): bool * @param $voucher * @return bool */ - public function rejectThisVoucher($voucher): bool + public function rejectThisVoucher($voucher) : bool { // return true, if any of these are true return // are all the fields we care about null? $this->containsOnlyNull($voucher) || // is this date filled? - !is_null($voucher['Void Voucher Date']) || - // is this date dilled *and* less than the cut-off date - ( - !is_null($voucher['Reimbursed Date']) && - strtotime( - DateTime::createFromFormat( - 'd/m/Y', - $voucher['Reimbursed Date'] - )->format('Y-m-d') - ) < strtotime($this->cutOffDate) - ); + !is_null($voucher['Void Voucher Date']); +// || +// // is this date dilled *and* less than the cut-off date +// (!is_null($voucher['Reimbursed Date']) && +// strtotime( +// DateTime::createFromFormat( +// 'd/m/Y', +// $voucher['Reimbursed Date'] +// )->format('Y-m-d') +// ) < strtotime($this->cutOffDate) +// ); } /** * @param $rows * @return void */ - public function writeMultiPartMVL($rows): void + public function writeMultiPartMVL($rows) : void { // set some loop controls $nextFile = true; @@ -474,7 +468,7 @@ public function writeMultiPartMVL($rows): void * @param $rows * @return void */ - public function writeAreaFiles($rows): void + public function writeAreaFiles($rows) : void { $areas = []; // We're going to use "&" references to avoid memory issues - Hang on to your hat. diff --git a/app/Console/Commands/MvlCat.php b/app/Console/Commands/MvlCat.php new file mode 100644 index 000000000..393b0bad6 --- /dev/null +++ b/app/Console/Commands/MvlCat.php @@ -0,0 +1,86 @@ +argument("file"); + + $this->info(sprintf("Reading logs from %s", $in_file)); + if (!file_exists($in_file)) { + $this->error(sprintf("Log file not found: %s", $in_file)); + } + + // Opens any given file from root folder - allows any encrypted file using SecretStreamWrapper to be decrypted. + // Might not be an issue, given that if a bad actor has access to ./artisan to run this we have bigger problems :) + $file = fopen($in_file, 'r'); + + // Get header for SSW. + $header = fread($file, SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_HEADERBYTES); + + + try { + // Initialise the decryption stream with its initial header. For more documentation, SecretStreamWrapper. + $stream = sodium_crypto_secretstream_xchacha20poly1305_init_pull($header, SecretStreamWrapper::getKey()); + } catch (\SodiumException $e) { + $this->error("Decryption stream could not be initialised."); + } + + do { + // Read the next message. + $part = fread($file, SecretStreamWrapper::MESSAGE_SIZE + SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_ABYTES); + + if ($part === false) { + // We couldn't read from the file. Log that as an error. + $this->error("IO error when reading log"); + } + + // Decrypt the message. + $part = sodium_crypto_secretstream_xchacha20poly1305_pull($stream, $part); + + if ($part === false) { + // Decryption failed. Log that as an error. + $this->error("Decryption error when reading log"); + } + + // Split the decrypted message into content and metadata. + list($message, $tag) = $part; + + // The last message should be tagged as such, to ensure there was no tampering after encryption. + $eof = feof($file); + $lastMessage = $tag === SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_TAG_FINAL; + if ($eof != $lastMessage) { + // We met the end of the file before the last message or vice-versa. Log that error. + $this->error("Log read ended prematurely"); + } + + // Stream the decrypted content. + echo $message; + } while (!$eof); // While there is more to do, continue. + + } +} diff --git a/app/Console/Commands/MvlCrypt.php b/app/Console/Commands/MvlCrypt.php new file mode 100644 index 000000000..2af1ac0e7 --- /dev/null +++ b/app/Console/Commands/MvlCrypt.php @@ -0,0 +1,65 @@ +argument("file"); + if (!file_exists($in_file)) { + $this->error(sprintf("File not found: %s", $in_file)); + } + + // Add encryption wrapper + if (!in_array("ssw", stream_get_wrappers())) { + stream_wrapper_register("ssw", "App\Wrappers\SecretStreamWrapper"); + } + + $targetDir = dirname($in_file); + $sswTargetDir = "ssw://" . $targetDir; + + $out_file = $sswTargetDir . "/" . $in_file . ".enc"; + $this->info(sprintf("Encrypting %s to %s", $in_file, $out_file)); + + $fh_out = fopen($out_file, 'w'); + $fh_in = fopen($in_file, "r"); + $iterator = $this->yeildyFileReader($fh_in); + + foreach ($iterator as $iteration) { + fputs($fh_out, $iteration); + } + + fclose($fh_in); + fclose($fh_out); + + stream_wrapper_unregister("ssw"); + } + + private function yeildyFileReader($handle) + { + while (!feof($handle)) { + yield trim(fgets($handle)); + } + } +} diff --git a/app/Console/Commands/MvlProcess.php b/app/Console/Commands/MvlProcess.php index 3d4e670df..ccbb7af20 100644 --- a/app/Console/Commands/MvlProcess.php +++ b/app/Console/Commands/MvlProcess.php @@ -62,20 +62,19 @@ public function handle(): void $this->error(sprintf("File not found: %s", $in_file)); } - $targetDir = dirname($in_file); - if (!file_exists($targetDir . "/_headers.csv")) { - if (!is_dir($targetDir)) { - mkdir($targetDir, 0755, true); - } - $fh = fopen($targetDir . "/_headers.csv", "w"); - fputcsv($fh, $this->headers); - fclose($fh); + // Add encryption wrapper + if (!in_array("ssw", stream_get_wrappers())) { + stream_wrapper_register("ssw", "App\Wrappers\SecretStreamWrapper"); } - $out_file = $targetDir . "/" . basename($in_file, ".txt") . ".csv"; + $targetDir = "storage/app/local"; + $sswTargetDir = "ssw://" . $targetDir; + + $out_file = $sswTargetDir . "/" . basename($in_file, ".txt") . ".csv"; $this->info(sprintf("Writing ids to %s", $out_file)); $fh_out = fopen($out_file, 'w'); + fputcsv($fh_out, $this->headers); $count = 0; $startTime = microtime(true); $time = microtime(true); @@ -85,7 +84,7 @@ public function handle(): void foreach ($lines as $id) { $v = Voucher::find($id); if ($v) { - fputcsv($fh_out, array_merge($v->deepExport(), $sharedData)); + fputcsv($fh_out, array_merge(array_values($v->deepExport()), $sharedData)); if ($count++ % self::TICK_SIZE === 0) { $this->info(sprintf( "Writing vouchers %d to %d, Mem: %s, elapsed time %f seconds", @@ -101,5 +100,7 @@ public function handle(): void $this->info("Total time: " . TextFormatter::secondsToTime(ceil(microtime(true) - $startTime))); fclose($fh_out); + + stream_wrapper_unregister("ssw"); } } diff --git a/app/Http/Controllers/Store/VoucherController.php b/app/Http/Controllers/Store/VoucherController.php index 09396a41e..0dd031b7e 100644 --- a/app/Http/Controllers/Store/VoucherController.php +++ b/app/Http/Controllers/Store/VoucherController.php @@ -3,8 +3,11 @@ namespace App\Http\Controllers\Store; use App\Http\Controllers\Controller; +use App\Services\TextFormatter; use App\Wrappers\SecretStreamWrapper; use Carbon\Carbon; +use Illuminate\Http\Request; +use Illuminate\Support\Facades\File; use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Storage; use Symfony\Component\HttpFoundation\StreamedResponse; @@ -15,7 +18,7 @@ class VoucherController extends Controller // This belongs here because it's largely about arranging vouchers public function exportMasterVoucherLog() { - // Setup the Storage dir. + // Set up the Storage dir. $disk = Storage::disk(config('arc.mvl_disk')); $archiveName = config('arc.mvl_filename'); @@ -28,10 +31,9 @@ public function exportMasterVoucherLog() } // Inject the original file last_modified into the d/l file name. - $filename = pathinfo($archiveName, PATHINFO_BASENAME) . + $filename = pathinfo($archiveName, PATHINFO_BASENAME) . "_" . strftime('%Y-%m-%d_%H%M', $disk->lastModified($archiveName)) . - "." . pathinfo($archiveName, PATHINFO_EXTENSION) - ; + "." . pathinfo($archiveName, PATHINFO_EXTENSION); // TODO : refactor SecretStreamWrapper to handle reads, decoupling this controller from crypto code @@ -86,7 +88,7 @@ public function exportMasterVoucherLog() } while (!$eof); // While there is more to do, continue. }, 200, [ 'Content-Type' => 'application/x-zip', - 'Content-Disposition' => 'attachment; filename="'. $filename .'"', + 'Content-Disposition' => 'attachment; filename="' . $filename . '"', 'Expires' => Carbon::createFromTimestamp(0)->format('D, d M Y H:i:s'), 'Last-Modified' => Carbon::now()->format('D, d M Y H:i:s'), 'Cache-Control' => 'private, no-cache', @@ -94,4 +96,112 @@ public function exportMasterVoucherLog() // TODO : Estimate zip size for a progress bar on what is quite a large file ]); } + + public function listVoucherLogs() + { + // by gabriel (intern 4) + + $directoryPath = storage_path("app/local"); # I think I'm using the wrong function to access files? + + $logFiles = File::glob($directoryPath . '/*.arcx.csv'); + + $downloadLinks = []; + $logMetadata = []; + foreach ($logFiles as $logFile) { + $baseFileName = basename($logFile); + + $downloadLinks[$baseFileName] = "/vouchers/download?logFile=" . $baseFileName; + + $rawFileSize = filesize($logFile); + + $formattedFileSize = TextFormatter::formatBytes($rawFileSize); + + $logMetadata[$baseFileName] = [ + "fileName" => $baseFileName, + "rawSize" => filesize($logFile), // Use for sorting. + "formattedSize" => $formattedFileSize, // Use for displaying. + "lastModified" => filemtime($logFile)]; + } + + return view('store.list_voucher_logs', ["downloadLinks" => $downloadLinks, "logMetadata" => $logMetadata]); + } + + public function downloadVoucherLogs(Request $request) + { + $logFile = $request->query('logFile'); + return response()->download(storage_path("app/local/" . $logFile)); + } + + + public function downloadAndDecryptVoucherLogs(Request $request) + { + $logFile = $request->query('logFile'); + // Is there a way for people to maliciously pass bad queries? + // I don't think they can do this, since it checks only searches within storage/app/local. + // The website will crash though if the file isn't encrypted properly/at all. + + $pathToVouchers = "app/local/"; + + // Check the log exists, so we can error-out before we declare a streamed response. + if (!file_exists(storage_path($pathToVouchers . $logFile))) { + // Return to dashboard with an error that indicates we don't have a file. + return redirect(URL::route('store.dashboard')) + ->with('error_message', "Sorry, we couldn't find the file you were looking for. Please contact support if this error persists."); + } + + // Do as much IO as we can comfortably before we begin streaming. + $file = fopen(storage_path($pathToVouchers . $logFile), 'r'); + + $header = fread($file, SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_HEADERBYTES); + + try { + // Initialise the decryption stream with its initial header. For more documentation, SecretStreamWrapper. + $stream = sodium_crypto_secretstream_xchacha20poly1305_init_pull($header, SecretStreamWrapper::getKey()); + } catch (\SodiumException $e) { + // TODO : This error copy needs some UI. + return redirect(URL::route('store.dashboard')) + ->with('error_message', "Sorry, the export file was unreadable. Please contact support."); + } + + # slightly (very) reused + return new StreamedResponse(function () use ($file, &$stream) { + do { + // Read the next message. + $part = fread($file, SecretStreamWrapper::MESSAGE_SIZE + SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_ABYTES); + + if ($part === false) { + // We couldn't read from the file. Log that as an error. + Log::error("IO error when reading log"); + throw new \RuntimeException("IO error when reading log"); + } + + // Decrypt the message. + $part = sodium_crypto_secretstream_xchacha20poly1305_pull($stream, $part); + + if ($part === false) { + // Decryption failed. Log that as an error. + Log::error("Decryption error when reading log"); + throw new \RuntimeException("Decryption error when reading log"); + } + + // Split the decrypted message into content and metadata. + list($message, $tag) = $part; + + // The last message should be tagged as such, to ensure there was no tampering after encryption. + $eof = feof($file); + $lastMessage = $tag === SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_TAG_FINAL; + if ($eof != $lastMessage) { + // We met the end of the file before the last message or vice-versa. Log that error. + Log::error("Log read ended prematurely"); + throw new \RuntimeException("Log read ended prematurely"); + } + + // Stream the decrypted content. + echo $message; + } while (!$eof); // While there is more to do, continue. + }, 200, [ + 'Content-Disposition' => 'attachment; filename="' . $logFile . '"' + ]); + + } } \ No newline at end of file diff --git a/app/Voucher.php b/app/Voucher.php index aac0baaa2..0e50db0e5 100644 --- a/app/Voucher.php +++ b/app/Voucher.php @@ -540,25 +540,53 @@ protected function serializeDate(DateTimeInterface $date) return $date->format('Y-m-d H:i:s'); } - public function deepExport(): array + public function getVoucherStateHistory(): array { - return [ - $this->code, - $this->sponsor?->name, - $this->delivery?->dispatched_at->format("Y/m/d"), - $this->delivery?->centre->name, - $this->delivery?->centre->sponsor->name, - $this->bundle?->disbursed_at ? "True" : "False", - $this->bundle?->disbursed_at?->format("Y/m/d"), - (string)$this->rvid(), - $this->bundle?->registration->family->carers[0]->name, - $this->bundle?->registration->centre->name, - $this->recordedOn->created_at->format("Y/m/d"), - $this->trader->name, - $this->trader->market->name, - $this->trader->market->sponsor->name, - $this->paymentPendedOn->created_at->format("Y/m/d"), - $this->reimbursedOn->created_at->format("Y/m/d"), + $vss = VoucherState::where("voucher_id", $this->id)->orderBy('updated_at')->get(); + $states = []; + if ($vss) { + foreach ($vss as $vs) { + $states[] = [ + "id" => $this->id, + "transition" => $vs->transition, + "from" => $vs->from, + "user_id" => $vs->user_id, + "user_type" => $vs->user_type, + "voucher_id" => $vs->voucher_id, + "to" => $vs->to, + "state_token_id" => $vs->state_token_id, + "source" => $vs->source, + "created_at" => $vs->created_at, + "updated_at" => $vs->updated_at, + ]; + } + } + return $states; + } + + public function deepExport(bool $includeVoucherStates = false): array + { + $v = [ + "code" => $this->code, + "sponsor_name" => $this->sponsor?->name, + "dispatched_at" => $this->delivery?->dispatched_at->format("Y/m/d"), + "delivery_centre_name" => $this->delivery?->centre->name, + "centre_sponsor_name" => $this->delivery?->centre->sponsor->name, + "disbursed" => $this->bundle?->disbursed_at ? "True" : "False", + "disbursed_at" => $this->bundle?->disbursed_at?->format("Y/m/d"), + "rvid" => (string)$this->rvid(), + "primary_carer" => $this->bundle?->registration->family->carers[0]->name, + "registration_centre_name," => $this->bundle?->registration->centre->name, + "recordedOn" => $this->recordedOn->created_at->format("Y/m/d"), + "trader_name" => $this->trader->name, + "trader_market_name" => $this->trader->market->name, + "trader_market_sponsor_name" => $this->trader->market->sponsor->name, + "paymentPendedOn" => $this->paymentPendedOn->created_at->format("Y/m/d"), + "reimbursedOn" => $this->reimbursedOn->created_at->format("Y/m/d"), ]; + if ($includeVoucherStates) { + $v["vouchere_states"] = $this->getVoucherStateHistory(); + } + return $v; } } diff --git a/app/VoucherState.php b/app/VoucherState.php index a05e29850..05b5de8bf 100644 --- a/app/VoucherState.php +++ b/app/VoucherState.php @@ -10,6 +10,7 @@ /** * @mixin Eloquent + * @property int $id; * @property string $transition; * @property string $from; * @property string $to; diff --git a/commitlint.config.js b/commitlint.config.js new file mode 100644 index 000000000..422b19445 --- /dev/null +++ b/commitlint.config.js @@ -0,0 +1 @@ +module.exports = { extends: ['@commitlint/config-conventional'] }; diff --git a/composer.lock b/composer.lock index 697ab3e6c..a32409ca6 100644 --- a/composer.lock +++ b/composer.lock @@ -4116,16 +4116,16 @@ }, { "name": "phenx/php-svg-lib", - "version": "0.5.0", + "version": "0.5.2", "source": { "type": "git", "url": "https://github.com/dompdf/php-svg-lib.git", - "reference": "76876c6cf3080bcb6f249d7d59705108166a6685" + "reference": "732faa9fb4309221e2bd9b2fda5de44f947133aa" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/dompdf/php-svg-lib/zipball/76876c6cf3080bcb6f249d7d59705108166a6685", - "reference": "76876c6cf3080bcb6f249d7d59705108166a6685", + "url": "https://api.github.com/repos/dompdf/php-svg-lib/zipball/732faa9fb4309221e2bd9b2fda5de44f947133aa", + "reference": "732faa9fb4309221e2bd9b2fda5de44f947133aa", "shasum": "" }, "require": { @@ -4156,9 +4156,9 @@ "homepage": "https://github.com/PhenX/php-svg-lib", "support": { "issues": "https://github.com/dompdf/php-svg-lib/issues", - "source": "https://github.com/dompdf/php-svg-lib/tree/0.5.0" + "source": "https://github.com/dompdf/php-svg-lib/tree/0.5.2" }, - "time": "2022-09-06T12:16:56+00:00" + "time": "2024-02-07T12:49:40+00:00" }, { "name": "phpoption/phpoption", @@ -4237,16 +4237,16 @@ }, { "name": "phpseclib/phpseclib", - "version": "3.0.20", + "version": "3.0.36", "source": { "type": "git", "url": "https://github.com/phpseclib/phpseclib.git", - "reference": "543a1da81111a0bfd6ae7bbc2865c5e89ed3fc67" + "reference": "c2fb5136162d4be18fdd4da9980696f3aee96d7b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/543a1da81111a0bfd6ae7bbc2865c5e89ed3fc67", - "reference": "543a1da81111a0bfd6ae7bbc2865c5e89ed3fc67", + "url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/c2fb5136162d4be18fdd4da9980696f3aee96d7b", + "reference": "c2fb5136162d4be18fdd4da9980696f3aee96d7b", "shasum": "" }, "require": { @@ -4327,7 +4327,7 @@ ], "support": { "issues": "https://github.com/phpseclib/phpseclib/issues", - "source": "https://github.com/phpseclib/phpseclib/tree/3.0.20" + "source": "https://github.com/phpseclib/phpseclib/tree/3.0.36" }, "funding": [ { @@ -4343,7 +4343,7 @@ "type": "tidelift" } ], - "time": "2023-06-13T06:30:34+00:00" + "time": "2024-02-26T05:13:14+00:00" }, { "name": "psr/cache", @@ -5013,16 +5013,16 @@ }, { "name": "sabberworm/php-css-parser", - "version": "8.4.0", + "version": "v8.5.1", "source": { "type": "git", - "url": "https://github.com/sabberworm/PHP-CSS-Parser.git", - "reference": "e41d2140031d533348b2192a83f02d8dd8a71d30" + "url": "https://github.com/MyIntervals/PHP-CSS-Parser.git", + "reference": "4a3d572b0f8b28bb6fd016ae8bbfc445facef152" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sabberworm/PHP-CSS-Parser/zipball/e41d2140031d533348b2192a83f02d8dd8a71d30", - "reference": "e41d2140031d533348b2192a83f02d8dd8a71d30", + "url": "https://api.github.com/repos/MyIntervals/PHP-CSS-Parser/zipball/4a3d572b0f8b28bb6fd016ae8bbfc445facef152", + "reference": "4a3d572b0f8b28bb6fd016ae8bbfc445facef152", "shasum": "" }, "require": { @@ -5030,13 +5030,17 @@ "php": ">=5.6.20" }, "require-dev": { - "codacy/coverage": "^1.4", - "phpunit/phpunit": "^4.8.36" + "phpunit/phpunit": "^5.7.27" }, "suggest": { "ext-mbstring": "for parsing UTF-8 CSS" }, "type": "library", + "extra": { + "branch-alias": { + "dev-main": "9.0.x-dev" + } + }, "autoload": { "psr-4": { "Sabberworm\\CSS\\": "src/" @@ -5049,6 +5053,14 @@ "authors": [ { "name": "Raphael Schweikert" + }, + { + "name": "Oliver Klee", + "email": "github@oliverklee.de" + }, + { + "name": "Jake Hotson", + "email": "jake.github@qzdesign.co.uk" } ], "description": "Parser for CSS Files written in PHP", @@ -5059,10 +5071,10 @@ "stylesheet" ], "support": { - "issues": "https://github.com/sabberworm/PHP-CSS-Parser/issues", - "source": "https://github.com/sabberworm/PHP-CSS-Parser/tree/8.4.0" + "issues": "https://github.com/MyIntervals/PHP-CSS-Parser/issues", + "source": "https://github.com/MyIntervals/PHP-CSS-Parser/tree/v8.5.1" }, - "time": "2021-12-11T13:40:54+00:00" + "time": "2024-02-15T16:41:13+00:00" }, { "name": "sebdesign/laravel-state-machine", @@ -12569,5 +12581,5 @@ "platform-overrides": { "php": "8.1" }, - "plugin-api-version": "2.2.0" + "plugin-api-version": "2.6.0" } diff --git a/config/logging.php b/config/logging.php index 25b6f3f3f..b1432fca5 100644 --- a/config/logging.php +++ b/config/logging.php @@ -61,6 +61,14 @@ 'path' => storage_path('logs/warning.log'), 'level' => 'warning', ], + + 'stderr' => [ + 'driver' => 'monolog', + 'handler' => StreamHandler::class, + 'with' => [ + 'stream' => 'php://stderr', + ], + ], ] // 'channels' => [ // // Aggregated logs, all channels listed in the channels array diff --git a/docs/DATABASE_SCHEMA.md b/docs/DATABASE_SCHEMA.md new file mode 100644 index 000000000..9dd734519 --- /dev/null +++ b/docs/DATABASE_SCHEMA.md @@ -0,0 +1,5 @@ +# Database Schema + +Defined in [database-structure.puml](images/database-structure.puml) + +![Transition table](images/database-structure.png "Database Schema") diff --git a/docs/DEPLOYMENT.md b/docs/DEPLOYMENT.md new file mode 100644 index 000000000..c02ba749d --- /dev/null +++ b/docs/DEPLOYMENT.md @@ -0,0 +1,58 @@ +## Physical server set up + +We have two Rocky linux virtual machines in a Digital Ocean cluster. The machines have their packages updated monthly. + +### Staging + +Basic / 4 GB / 2 vCPUs / 80Gb / $24.00 per month + +### Live + +8 GB / 4 vCPUs / 160Gb / $48.00 per month + +## Software stacks + +The staging server was hand rolled to provide the LAMP stack below. Live was a VM clone of staging. These have been live since March 2023 so may have some package drift. + +``` +[neontribe@rocky9-arc-staging ~]$ apachectl -v +Server version: Apache/2.4.57 (Rocky Linux) +Server built: Jul 20 2023 00:00:00 +[neontribe@rocky9-arc-staging ~]$ php-cgi -v +PHP 8.1.26 (cgi-fcgi) (built: Nov 21 2023 21:53:48) +Copyright (c) The PHP Group +Zend Engine v4.1.26, Copyright (c) Zend Technologies + with Zend OPcache v8.1.26, Copyright (c), by Zend Technologies +[neontribe@rocky9-arc-staging ~]$ mysqld -V +/usr/libexec/mysqld Ver 8.0.32 for Linux on x86_64 (Source distribution) +``` + +The ARC service comprises two server applications and one Vue.js single page app. + +The server applications are both served from a single Laravel stack, switched on virtual host by Laravel. These persist shared data into a mysql server. The raw mysql files for this instance are: + +``` +[root@rocky9-arc-staging mysql]# du -sh . +208M . +``` + +``` +[root@Arc-live-04-2023 mysql]# du -sh . +20G . +``` + +The Vue.js (2.x) single page application is served as statically built files that are served by the Apache instance via virtual host named switching. This app uses the Laravel instance as REST API to read/write data and carry out operations requested by the user. + +The Vue.js application may be optionally persisted on phones that support the progressive web app conventions. It uses a service worker to cache locally and fetch new variations from the server when it sees them. + +## Service Interaction + +Defined in [server-components.puml](images/server-components.puml) + +![Transition table](images/server-components.png "Service Interactions") + +## SupervisorD and CronD managed processes + +The system uses [Supervisord](http://supervisord.org/) to run a database backed queue worker with responsibilities like processing long-running tasks like fetching voucher histories. + +There is a cron job that is run very frequently to execute Laravel's internal [task scheduling system](../app/Console/Kernel.php) diff --git a/docs/MVL-EXPORT.md b/docs/MVL-EXPORT.md index 18c37714b..6c546402d 100644 --- a/docs/MVL-EXPORT.md +++ b/docs/MVL-EXPORT.md @@ -28,10 +28,10 @@ Does what it says, it exports data into one file for each financial year up to 2 This takes a directory as input and processes all `.arcx` files in that directory into `.csv` files with a [deep export](https://github.com/neontribe/ARCVService/blob/develop/app/Voucher.php#:~:text=) row of fields. It also creates a file called `_headers.csv` that has the csv row headers. -After running the process commad you can concatonate the csv files into a single file using: +After running the process command you can concatenate the csv files into a single file using: ```bash cat *.csv > /path/to/dest/FILENAME.csv ``` -**N.B.** These csv files are processed using excel so may not contain more than 1,000,000 rows. \ No newline at end of file +**N.B.** These csv files are processed using excel so may not contain more than 1,000,000 rows. diff --git a/docs/README.md b/docs/README.md index 6a8a433b4..4f1832fd7 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,37 +1,9 @@ +# ARC Docs +## Table of contents -## Links - - * [Using Plant UML to generate diagrams](plantuml.md) - -## Voucher state transitions - -Defined in [voucher-state-transitions.txt](voucher-state-transitions.txt) - -![Transition table](voucher-state-transitions.png "Voucher transitions") - -## Setting up vouchers for testing MVL - -The seeder and the [VoucherState::batchInsert](https://github.com/neontribe/ARCVService/blob/84ec961bc7074c0aff1f6f2a09311a2ad6d9c94e/app/VoucherState.php#L49) overrides the created date with `now` so all our voucher states are clumped in a single day. - -You need to run some sql to do that. - -### Create the stored procedure - -If you are using the [dev-helper](https://github.com/neontribe/ARCVInfra/tree/main/docker/dev-helper) docker stack: - - mysql -ulamp -plamp -P3336 -h127.0.0.1 lamp < docs/create-randomise-voucher-states.sql - -Otherwise, you'll need to connect to mysql and run it yourself. I think homestead users can do this, but I'm not sure, please update this document if this is wrong: - - mysql -uhomestead -psecret -P3306 -h127.0.0.1 homestead < docs/create-randomise-voucher-states.sql - -### Run it - -Just connect to the mysql instance and call it, dev help version: - - mysql -ulamp -plamp -P3336 -h127.0.0.1 lamp -e "CALL UpdateRandomTimestamps();" - -And then check it worked: - - select count(*), created_at from voucher_states where `to` = 'reimbursed' group by created_at limit 30; + * [Deployment set up](./DEPLOYMENT.md); some notes on how the system's components hang together + * [MVL Export](./MVL-EXPORT.md); reference for commands used to export reports required by ARC + * [Setting up testing vouchers](./TEST_VOUCHERS.md); reference for populating the dataset for substantial numbers of vouchers + * [Voucher state transition](./VOUCHER_STATE_TRANSITIONS.md); reference for the voucher state machine that are enforces valid voucher state flow + * [Database schema](./DATABASE_SCHEMA.md); reference diagram of the current database schema diff --git a/docs/TEST_VOUCHERS.md b/docs/TEST_VOUCHERS.md new file mode 100644 index 000000000..ca052c3ac --- /dev/null +++ b/docs/TEST_VOUCHERS.md @@ -0,0 +1,32 @@ +## Voucher state transitions + +Defined in [voucher-state-transitions.txt](voucher-state-transitions.puml) + +![Transition table](./images/voucher-state-transitions.png "Voucher transitions") + +## Setting up vouchers for testing MVL + +The seeder and the [VoucherState::batchInsert](https://github.com/neontribe/ARCVService/blob/84ec961bc7074c0aff1f6f2a09311a2ad6d9c94e/app/VoucherState.php#L49) overrides the created date with `now` so all our voucher states are clumped in a single day. + +You need to run some sql to do that. + +### Create the stored procedure + +If you are using the [dev-helper](https://github.com/neontribe/ARCVInfra/tree/main/docker/dev-helper) docker stack: + + mysql -ulamp -plamp -P3336 -h127.0.0.1 lamp < docs/create-randomise-voucher-states.sql + +Otherwise, you'll need to connect to mysql and run it yourself. I think homestead users can do this, but I'm not sure, please update this document if this is wrong: + + mysql -uhomestead -psecret -P3306 -h127.0.0.1 homestead < docs/create-randomise-voucher-states.sql + +### Run it + +Just connect to the mysql instance and call it, dev help version: + + mysql -ulamp -plamp -P3336 -h127.0.0.1 lamp -e "CALL UpdateRandomTimestamps();" + +And then check it worked: + + select count(*), created_at from voucher_states where `to` = 'reimbursed' group by created_at limit 30; + diff --git a/docs/VOUCHER_STATE_TRANSITIONS.md b/docs/VOUCHER_STATE_TRANSITIONS.md new file mode 100644 index 000000000..438e2068b --- /dev/null +++ b/docs/VOUCHER_STATE_TRANSITIONS.md @@ -0,0 +1,5 @@ +# Voucher state transitions + +Defined in [voucher-state-transitions.puml](images/voucher-state-transitions.puml) + +![Transition table](images/voucher-state-transitions.png "Voucher transitions") \ No newline at end of file diff --git a/docs/ERD.png b/docs/images/ERD.png similarity index 100% rename from docs/ERD.png rename to docs/images/ERD.png diff --git a/docs/images/database-structure.png b/docs/images/database-structure.png new file mode 100644 index 000000000..bcc738a79 Binary files /dev/null and b/docs/images/database-structure.png differ diff --git a/docs/images/database-structure.puml b/docs/images/database-structure.puml new file mode 100644 index 000000000..51ca7d744 --- /dev/null +++ b/docs/images/database-structure.puml @@ -0,0 +1,337 @@ +@startuml + +top to bottom direction +skinparam linetype ortho + +class admin_users { + name: varchar(191) + email: varchar(191) + password: varchar(191) + remember_token: varchar(100) + created_at: timestamp + updated_at: timestamp + deleted_at: timestamp + id: int(10) unsigned +} +class bundles { + entitlement: int(10) unsigned + registration_id: int(10) unsigned + collecting_carer_id: int(10) unsigned + disbursing_centre_id: int(10) unsigned + disbursing_user_id: int(10) unsigned + disbursed_at: timestamp + created_at: timestamp + updated_at: timestamp + id: int(10) unsigned +} +class carers { + name: varchar(191) + family_id: int(10) unsigned + created_at: timestamp + updated_at: timestamp + deleted_at: timestamp + ethnicity: varchar(191) + language: varchar(191) + id: int(10) unsigned +} +class centre_centre_user { + homeCentre: tinyint(1) + centre_user_id: int(10) unsigned + centre_id: int(10) unsigned +} +class centre_users { + name: varchar(191) + email: varchar(191) + password: varchar(191) + role: varchar(191) + downloader: tinyint(1) + remember_token: varchar(100) + centre_id: int(10) unsigned + created_at: timestamp + updated_at: timestamp + deleted_at: timestamp + id: int(10) unsigned +} +class centres { + name: varchar(191) + prefix: varchar(5) + sponsor_id: int(10) unsigned + print_pref: enum('collection', 'individual') + created_at: timestamp + updated_at: timestamp + id: int(10) unsigned +} +class children { + dob: datetime + born: tinyint(1) + verified: tinyint(1) + family_id: int(10) unsigned + created_at: timestamp + updated_at: timestamp + deferred: tinyint(1) + is_pri_carer: tinyint(1) + id: int(10) unsigned +} +class deliveries { + centre_id: int(10) unsigned + range: varchar(191) + dispatched_at: datetime + created_at: timestamp + updated_at: timestamp + id: int(10) unsigned +} +class evaluations { + sponsor_id: int(11) + name: varchar(191) + entity: varchar(191) + purpose: varchar(191) + value: int(11) + created_at: timestamp + updated_at: timestamp + id: int(10) unsigned +} +class failed_jobs { + uuid: varchar(191) + connection: text + queue: text + payload: longtext + exception: longtext + failed_at: timestamp + id: bigint(20) unsigned +} +class families { + initial_centre_id: int(10) unsigned + centre_sequence: int(11) + leaving_on: datetime + leaving_reason: varchar(128) + created_at: timestamp + updated_at: timestamp + rejoin_on: timestamp + leave_amount: int(11) + id: int(10) unsigned +} +class job_statuses { + job_id: varchar(191) + type: varchar(191) + queue: varchar(191) + attempts: int(11) + progress_now: int(11) + progress_max: int(11) + status: varchar(16) + input: longtext + output: longtext + created_at: timestamp + updated_at: timestamp + started_at: timestamp + finished_at: timestamp + id: int(10) unsigned +} +class jobs { + queue: varchar(191) + payload: longtext + attempts: tinyint(3) unsigned + reserved_at: int(10) unsigned + available_at: int(10) unsigned + created_at: int(10) unsigned + id: bigint(20) unsigned +} +class market_logs { + created_at: timestamp + updated_at: timestamp + url: varchar(191) + status: int(11) + created: varchar(191) + data: longtext + hash: varchar(191) + trader_id: int(11) + id: int(10) unsigned +} +class markets { + name: varchar(191) + location: varchar(191) + sponsor_id: int(10) unsigned + created_at: timestamp + updated_at: timestamp + deleted_at: timestamp + payment_message: varchar(191) + id: int(10) unsigned +} +class migrations { + migration: varchar(191) + batch: int(11) + id: int(10) unsigned +} +class notes { + content: text + family_id: int(10) unsigned + user_id: int(10) unsigned + created_at: timestamp + updated_at: timestamp + id: int(10) unsigned +} +class oauth_access_tokens { + user_id: bigint(20) unsigned + client_id: bigint(20) unsigned + name: varchar(191) + scopes: text + revoked: tinyint(1) + created_at: timestamp + updated_at: timestamp + expires_at: datetime + id: varchar(100) +} +class oauth_auth_codes { + user_id: bigint(20) unsigned + client_id: bigint(20) unsigned + scopes: text + revoked: tinyint(1) + expires_at: datetime + id: varchar(100) +} +class oauth_clients { + user_id: bigint(20) unsigned + name: varchar(191) + secret: varchar(100) + provider: varchar(191) + redirect: text + personal_access_client: tinyint(1) + password_client: tinyint(1) + revoked: tinyint(1) + created_at: timestamp + updated_at: timestamp + id: bigint(20) unsigned +} +class oauth_personal_access_clients { + client_id: bigint(20) unsigned + created_at: timestamp + updated_at: timestamp + id: bigint(20) unsigned +} +class oauth_refresh_tokens { + access_token_id: varchar(100) + revoked: tinyint(1) + expires_at: datetime + id: varchar(100) +} +class password_resets { + email: varchar(191) + token: varchar(191) + created_at: timestamp +} +class registrations { + family_id: int(10) unsigned + centre_id: int(10) unsigned + eligibility_nrpf: varchar(191) + eligibility_hsbs: varchar(191) + consented_on: datetime + created_at: timestamp + updated_at: timestamp + eligible_from: timestamp + id: int(10) unsigned +} +class sponsors { + name: varchar(191) + shortcode: varchar(191) + programme: int(11) + created_at: timestamp + updated_at: timestamp + deleted_at: timestamp + can_tap: tinyint(1) + id: int(10) unsigned +} +class state_tokens { + uuid: varchar(191) + user_id: int(10) unsigned + created_at: timestamp + admin_user_id: int(10) unsigned + updated_at: timestamp + id: int(10) unsigned +} +class trader_user { + trader_id: int(10) unsigned + user_id: int(10) unsigned +} +class traders { + name: varchar(191) + pic_url: varchar(191) + market_id: int(10) unsigned + created_at: timestamp + updated_at: timestamp + deleted_at: timestamp + disabled_at: timestamp + id: int(10) unsigned +} +class users { + name: varchar(191) + email: varchar(191) + password: varchar(191) + remember_token: varchar(100) + created_at: timestamp + updated_at: timestamp + deleted_at: timestamp + id: int(10) unsigned +} +class voucher_states { + transition: varchar(191) + from: varchar(191) + user_id: int(10) unsigned + user_type: varchar(191) + voucher_id: int(10) unsigned + to: varchar(191) + state_token_id: int(10) unsigned + source: varchar(191) + created_at: timestamp + updated_at: timestamp + id: int(10) unsigned +} +class vouchers { + bundle_id: int(10) unsigned + delivery_id: int(10) unsigned + trader_id: int(10) unsigned + code: varchar(32) + currentstate: varchar(24) + sponsor_id: int(10) unsigned + created_at: timestamp + updated_at: timestamp + deleted_at: timestamp + id: int(10) unsigned +} + +bundles -[#595959,plain]-^ carers : "collecting_carer_id:id" +bundles -[#595959,plain]-^ centre_users : "disbursing_user_id:id" +bundles -[#595959,plain]-^ centres : "disbursing_centre_id:id" +bundles -[#595959,plain]-^ registrations : "registration_id:id" +carers -[#595959,plain]-^ families : "family_id:id" +centre_centre_user -[#595959,plain]-^ centre_users : "centre_user_id:id" +centre_centre_user -[#595959,plain]-^ centres : "centre_id:id" +centre_users -[#595959,plain]-^ centres : "centre_id:id" +centres -[#595959,plain]-^ sponsors : "sponsor_id:id" +children -[#595959,plain]-^ families : "family_id:id" +deliveries -[#595959,plain]-^ centres : "centre_id:id" +evaluations -[#595959,plain]-^ sponsors : "sponsor_id:id" +families -[#595959,plain]-^ centres : "initial_centre_id:id" +job_statuses -[#595959,plain]-^ jobs : "job_id:id" +market_logs -[#595959,plain]-^ traders : "trader_id:id" +markets -[#595959,plain]-^ sponsors : "sponsor_id:id" +notes -[#595959,plain]-^ centre_users : "user_id:id" +notes -[#595959,plain]-^ families : "family_id:id" +notes -[#595959,plain]-^ users : "user_id:id" +oauth_access_tokens -[#595959,plain]-^ users : "user_id:id" +oauth_auth_codes -[#595959,plain]-^ users : "user_id:id" +oauth_clients -[#595959,plain]-^ users : "user_id:id" +registrations -[#595959,plain]-^ centres : "centre_id:id" +registrations -[#595959,plain]-^ families : "family_id:id" +state_tokens -[#595959,plain]-^ admin_users : "admin_user_id:id" +state_tokens -[#595959,plain]-^ users : "user_id:id" +trader_user -[#595959,plain]-^ traders : "trader_id:id" +trader_user -[#595959,plain]-^ users : "user_id:id" +traders -[#595959,plain]-^ markets : "market_id:id" +voucher_states -[#595959,plain]-^ state_tokens : "state_token_id:id" +voucher_states -[#595959,plain]-^ users : "user_id:id" +voucher_states -[#595959,plain]-^ vouchers : "voucher_id:id" +vouchers -[#595959,plain]-^ bundles : "bundle_id:id" +vouchers -[#595959,plain]-^ deliveries : "delivery_id:id" +vouchers -[#595959,plain]-^ sponsors : "sponsor_id:id" +vouchers -[#595959,plain]-^ traders : "trader_id:id" +@enduml + diff --git a/docs/plantuml.md b/docs/images/plantuml.md similarity index 87% rename from docs/plantuml.md rename to docs/images/plantuml.md index 32f128b20..e5194045e 100644 --- a/docs/plantuml.md +++ b/docs/images/plantuml.md @@ -9,6 +9,6 @@ ### Create png from plantuml spec ```bash -plantuml docs/voucher-state-transitions.txt +plantuml docs/voucher-state-transitions.puml ``` diff --git a/docs/images/server-components.png b/docs/images/server-components.png new file mode 100644 index 000000000..b8ff013f4 Binary files /dev/null and b/docs/images/server-components.png differ diff --git a/docs/images/server-components.puml b/docs/images/server-components.puml new file mode 100644 index 000000000..650062de2 --- /dev/null +++ b/docs/images/server-components.puml @@ -0,0 +1,22 @@ +@startuml + +package "systemd" { + [supervisord] +} + +package [PHP] { + https - [Fast CGI] + [CLI] +} + +database "MySql" { + folder "Shared store/admin DB" { + [DB] + } +} + +[Fast CGI] --> [DB] +[CLI] --> [DB] +[supervisord] -> [CLI] + +@enduml diff --git a/docs/voucher-state-transitions.png b/docs/images/voucher-state-transitions.png similarity index 100% rename from docs/voucher-state-transitions.png rename to docs/images/voucher-state-transitions.png diff --git a/docs/voucher-state-transitions.txt b/docs/images/voucher-state-transitions.puml similarity index 100% rename from docs/voucher-state-transitions.txt rename to docs/images/voucher-state-transitions.puml diff --git a/docs/voucher-state-transitions.md b/docs/voucher-state-transitions.md deleted file mode 100644 index 32102fd21..000000000 --- a/docs/voucher-state-transitions.md +++ /dev/null @@ -1,5 +0,0 @@ -# Voucher state transitions - -Defined in [voucher-state-transitions.txt](voucher-state-transitions.txt) - -![Transition table](voucher-state-transitions.png "Voucher transitions") \ No newline at end of file diff --git a/package.json b/package.json index bba7af8a4..216361272 100644 --- a/package.json +++ b/package.json @@ -7,10 +7,16 @@ "watch-poll": "mix watch -- --watch-options-poll=1000", "hot": "mix watch --hot", "prod": "yarn production", - "production": "mix --production" + "production": "mix --production", + "prepare": "husky", + "commitlint": "commitlint --edit", + "test": "" }, "devDependencies": { + "@commitlint/cli": "^18.6.1", + "@commitlint/config-conventional": "^18.6.2", "bootstrap-sass": "^3.4.3", + "husky": "^9.0.11", "jquery": "^3.6.4", "jquery-ui": "^1.13.2", "laravel-mix": "^6.0.49", @@ -18,6 +24,9 @@ "sass": "^1.62.0", "sass-loader": "^13.2.2" }, + "scripts": { + "postinstall": "husky install" + }, "browserslist": [ ">2%", "ie 11", diff --git a/resources/views/store/dashboard.blade.php b/resources/views/store/dashboard.blade.php index cbffc9e01..b511baf6b 100644 --- a/resources/views/store/dashboard.blade.php +++ b/resources/views/store/dashboard.blade.php @@ -57,6 +57,12 @@ Export Voucher Log + +
  • + + View Historic Voucher Logs +
  • +
    @endcan diff --git a/resources/views/store/list_voucher_logs.blade.php b/resources/views/store/list_voucher_logs.blade.php new file mode 100644 index 000000000..1c8e59ac8 --- /dev/null +++ b/resources/views/store/list_voucher_logs.blade.php @@ -0,0 +1,47 @@ +{{--by intern 4--}} + +@extends('store.layouts.service_master') + +@section('title', 'Voucher Log Downloads') + +@section('content') + +@include('store.partials.navbar', ['headerTitle' => 'Export Voucher Logs']) + + +
    + +
    + + + +@endsection diff --git a/routes/store.php b/routes/store.php index e368a6cd0..bb7d6ef64 100644 --- a/routes/store.php +++ b/routes/store.php @@ -166,6 +166,19 @@ function () { 'as' => 'store.vouchers.mvl.export', 'uses' => 'VoucherController@exportMasterVoucherLog', ]); + + // Table of all historical voucher logs stored in our system. + Route::get('/vouchers/historical', [ + 'as' => 'store.vouchers.mvl.historical', + 'uses' => 'VoucherController@listVoucherLogs', + ]); + + // Downloads and decrypts voucher log file when the button at /vouchers/historical is pressed. + Route::get('/vouchers/download', [ + 'as' => 'store.vouchers.mvl.download', + 'uses' => 'VoucherController@downloadAndDecryptVoucherLogs', + ]); + } ); diff --git a/yarn.lock b/yarn.lock index 227f6c9ca..7bc43c9a1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -927,6 +927,164 @@ resolved "https://registry.yarnpkg.com/@colors/colors/-/colors-1.5.0.tgz#bb504579c1cae923e6576a4f5da43d25f97bdbd9" integrity sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ== +"@commitlint/cli@^18.6.1": + version "18.6.1" + resolved "https://registry.yarnpkg.com/@commitlint/cli/-/cli-18.6.1.tgz#78bffdfa00d6f01425d53096954993d83f2b343d" + integrity sha512-5IDE0a+lWGdkOvKH892HHAZgbAjcj1mT5QrfA/SVbLJV/BbBMGyKN0W5mhgjekPJJwEQdVNvhl9PwUacY58Usw== + dependencies: + "@commitlint/format" "^18.6.1" + "@commitlint/lint" "^18.6.1" + "@commitlint/load" "^18.6.1" + "@commitlint/read" "^18.6.1" + "@commitlint/types" "^18.6.1" + execa "^5.0.0" + lodash.isfunction "^3.0.9" + resolve-from "5.0.0" + resolve-global "1.0.0" + yargs "^17.0.0" + +"@commitlint/config-conventional@^18.6.2": + version "18.6.2" + resolved "https://registry.yarnpkg.com/@commitlint/config-conventional/-/config-conventional-18.6.2.tgz#617f3ee761578040cade530631058699642cbd78" + integrity sha512-PcgSYg1AKGQIwDQKbaHtJsfqYy4uJTC7crLVZ83lfjcPaec4Pry2vLeaWej7ao2KsT20l9dWoMPpEGg8LWdUuA== + dependencies: + "@commitlint/types" "^18.6.1" + conventional-changelog-conventionalcommits "^7.0.2" + +"@commitlint/config-validator@^18.6.1": + version "18.6.1" + resolved "https://registry.yarnpkg.com/@commitlint/config-validator/-/config-validator-18.6.1.tgz#e0d71a99c984a68586c7ae7afd3f52342022fae8" + integrity sha512-05uiToBVfPhepcQWE1ZQBR/Io3+tb3gEotZjnI4tTzzPk16NffN6YABgwFQCLmzZefbDcmwWqJWc2XT47q7Znw== + dependencies: + "@commitlint/types" "^18.6.1" + ajv "^8.11.0" + +"@commitlint/ensure@^18.6.1": + version "18.6.1" + resolved "https://registry.yarnpkg.com/@commitlint/ensure/-/ensure-18.6.1.tgz#17141e083200ca94d8480dc23b0e8f8b1fd37b7f" + integrity sha512-BPm6+SspyxQ7ZTsZwXc7TRQL5kh5YWt3euKmEIBZnocMFkJevqs3fbLRb8+8I/cfbVcAo4mxRlpTPfz8zX7SnQ== + dependencies: + "@commitlint/types" "^18.6.1" + lodash.camelcase "^4.3.0" + lodash.kebabcase "^4.1.1" + lodash.snakecase "^4.1.1" + lodash.startcase "^4.4.0" + lodash.upperfirst "^4.3.1" + +"@commitlint/execute-rule@^18.6.1": + version "18.6.1" + resolved "https://registry.yarnpkg.com/@commitlint/execute-rule/-/execute-rule-18.6.1.tgz#18175e043fe6fb5fceea7b8530316c644f93dfe6" + integrity sha512-7s37a+iWyJiGUeMFF6qBlyZciUkF8odSAnHijbD36YDctLhGKoYltdvuJ/AFfRm6cBLRtRk9cCVPdsEFtt/2rg== + +"@commitlint/format@^18.6.1": + version "18.6.1" + resolved "https://registry.yarnpkg.com/@commitlint/format/-/format-18.6.1.tgz#5f2b8b3ae4d8d80bd9239178e97df63e5b8d280a" + integrity sha512-K8mNcfU/JEFCharj2xVjxGSF+My+FbUHoqR+4GqPGrHNqXOGNio47ziiR4HQUPKtiNs05o8/WyLBoIpMVOP7wg== + dependencies: + "@commitlint/types" "^18.6.1" + chalk "^4.1.0" + +"@commitlint/is-ignored@^18.6.1": + version "18.6.1" + resolved "https://registry.yarnpkg.com/@commitlint/is-ignored/-/is-ignored-18.6.1.tgz#4ee08ba91ff3defb06e0ef19259a9c6734a8d06e" + integrity sha512-MOfJjkEJj/wOaPBw5jFjTtfnx72RGwqYIROABudOtJKW7isVjFe9j0t8xhceA02QebtYf4P/zea4HIwnXg8rvA== + dependencies: + "@commitlint/types" "^18.6.1" + semver "7.6.0" + +"@commitlint/lint@^18.6.1": + version "18.6.1" + resolved "https://registry.yarnpkg.com/@commitlint/lint/-/lint-18.6.1.tgz#fe3834636c99ee14534a8eb3832831ac362e9fd8" + integrity sha512-8WwIFo3jAuU+h1PkYe5SfnIOzp+TtBHpFr4S8oJWhu44IWKuVx6GOPux3+9H1iHOan/rGBaiacicZkMZuluhfQ== + dependencies: + "@commitlint/is-ignored" "^18.6.1" + "@commitlint/parse" "^18.6.1" + "@commitlint/rules" "^18.6.1" + "@commitlint/types" "^18.6.1" + +"@commitlint/load@^18.6.1": + version "18.6.1" + resolved "https://registry.yarnpkg.com/@commitlint/load/-/load-18.6.1.tgz#fb79ed7ee8b5897a9b5c274c1e24eda9162df816" + integrity sha512-p26x8734tSXUHoAw0ERIiHyW4RaI4Bj99D8YgUlVV9SedLf8hlWAfyIFhHRIhfPngLlCe0QYOdRKYFt8gy56TA== + dependencies: + "@commitlint/config-validator" "^18.6.1" + "@commitlint/execute-rule" "^18.6.1" + "@commitlint/resolve-extends" "^18.6.1" + "@commitlint/types" "^18.6.1" + chalk "^4.1.0" + cosmiconfig "^8.3.6" + cosmiconfig-typescript-loader "^5.0.0" + lodash.isplainobject "^4.0.6" + lodash.merge "^4.6.2" + lodash.uniq "^4.5.0" + resolve-from "^5.0.0" + +"@commitlint/message@^18.6.1": + version "18.6.1" + resolved "https://registry.yarnpkg.com/@commitlint/message/-/message-18.6.1.tgz#107bd40923ad23d2de56c92a68b179ebfb7e314e" + integrity sha512-VKC10UTMLcpVjMIaHHsY1KwhuTQtdIKPkIdVEwWV+YuzKkzhlI3aNy6oo1eAN6b/D2LTtZkJe2enHmX0corYRw== + +"@commitlint/parse@^18.6.1": + version "18.6.1" + resolved "https://registry.yarnpkg.com/@commitlint/parse/-/parse-18.6.1.tgz#2946b814125e907b9c4d63d3e71d0c1b54b30b62" + integrity sha512-eS/3GREtvVJqGZrwAGRwR9Gdno3YcZ6Xvuaa+vUF8j++wsmxrA2En3n0ccfVO2qVOLJC41ni7jSZhQiJpMPGOQ== + dependencies: + "@commitlint/types" "^18.6.1" + conventional-changelog-angular "^7.0.0" + conventional-commits-parser "^5.0.0" + +"@commitlint/read@^18.6.1": + version "18.6.1" + resolved "https://registry.yarnpkg.com/@commitlint/read/-/read-18.6.1.tgz#8c138311ed9749427920c369f6276be136f2aa50" + integrity sha512-ia6ODaQFzXrVul07ffSgbZGFajpe8xhnDeLIprLeyfz3ivQU1dIoHp7yz0QIorZ6yuf4nlzg4ZUkluDrGN/J/w== + dependencies: + "@commitlint/top-level" "^18.6.1" + "@commitlint/types" "^18.6.1" + git-raw-commits "^2.0.11" + minimist "^1.2.6" + +"@commitlint/resolve-extends@^18.6.1": + version "18.6.1" + resolved "https://registry.yarnpkg.com/@commitlint/resolve-extends/-/resolve-extends-18.6.1.tgz#f0572c682fc24dbabe2e0f42873261e0fa42c91a" + integrity sha512-ifRAQtHwK+Gj3Bxj/5chhc4L2LIc3s30lpsyW67yyjsETR6ctHAHRu1FSpt0KqahK5xESqoJ92v6XxoDRtjwEQ== + dependencies: + "@commitlint/config-validator" "^18.6.1" + "@commitlint/types" "^18.6.1" + import-fresh "^3.0.0" + lodash.mergewith "^4.6.2" + resolve-from "^5.0.0" + resolve-global "^1.0.0" + +"@commitlint/rules@^18.6.1": + version "18.6.1" + resolved "https://registry.yarnpkg.com/@commitlint/rules/-/rules-18.6.1.tgz#da25aeffe6c0e1c7625e44f46089fb8860986caf" + integrity sha512-kguM6HxZDtz60v/zQYOe0voAtTdGybWXefA1iidjWYmyUUspO1zBPQEmJZ05/plIAqCVyNUTAiRPWIBKLCrGew== + dependencies: + "@commitlint/ensure" "^18.6.1" + "@commitlint/message" "^18.6.1" + "@commitlint/to-lines" "^18.6.1" + "@commitlint/types" "^18.6.1" + execa "^5.0.0" + +"@commitlint/to-lines@^18.6.1": + version "18.6.1" + resolved "https://registry.yarnpkg.com/@commitlint/to-lines/-/to-lines-18.6.1.tgz#d28827a4a540c98eea1aae31dafd66f80b2f1b9e" + integrity sha512-Gl+orGBxYSNphx1+83GYeNy5N0dQsHBQ9PJMriaLQDB51UQHCVLBT/HBdOx5VaYksivSf5Os55TLePbRLlW50Q== + +"@commitlint/top-level@^18.6.1": + version "18.6.1" + resolved "https://registry.yarnpkg.com/@commitlint/top-level/-/top-level-18.6.1.tgz#429fcb985e3beaba9b17e05c0ae61926c647baf0" + integrity sha512-HyiHQZUTf0+r0goTCDs/bbVv/LiiQ7AVtz6KIar+8ZrseB9+YJAIo8HQ2IC2QT1y3N1lbW6OqVEsTHjbT6hGSw== + dependencies: + find-up "^5.0.0" + +"@commitlint/types@^18.6.1": + version "18.6.1" + resolved "https://registry.yarnpkg.com/@commitlint/types/-/types-18.6.1.tgz#7eb3ab2d799d9166fbb98b96b0744581e59a4ad4" + integrity sha512-gwRLBLra/Dozj2OywopeuHj2ac26gjGkz2cZ+86cTJOdtWfiRRr4+e77ZDAGc6MDWxaWheI+mAV5TLWWRwqrFg== + dependencies: + chalk "^4.1.0" + "@discoveryjs/json-ext@^0.5.0": version "0.5.7" resolved "https://registry.yarnpkg.com/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz#1d572bfbbe14b7704e0ba0f39b74815b84870d70" @@ -1185,11 +1343,21 @@ resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-5.1.2.tgz#07508b45797cb81ec3f273011b054cd0755eddca" integrity sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA== +"@types/minimist@^1.2.0": + version "1.2.5" + resolved "https://registry.yarnpkg.com/@types/minimist/-/minimist-1.2.5.tgz#ec10755e871497bcd83efe927e43ec46e8c0747e" + integrity sha512-hov8bUuiLiyFPGyFPE1lwWhmzYbirOXQNNo40+y3zow8aFVTeyn3VWL0VFFfdNddA8S4Vf0Tc062rzyNr7Paag== + "@types/node@*": version "18.15.11" resolved "https://registry.yarnpkg.com/@types/node/-/node-18.15.11.tgz#b3b790f09cb1696cffcec605de025b088fa4225f" integrity sha512-E5Kwq2n4SbMzQOn6wnmBjuK9ouqlURrcZDVfbo9ftDDTFt3nk7ZKK4GMOzoYgnpQJKcxwQw+lGaBvvlMo0qN/Q== +"@types/normalize-package-data@^2.4.0": + version "2.4.4" + resolved "https://registry.yarnpkg.com/@types/normalize-package-data/-/normalize-package-data-2.4.4.tgz#56e2cc26c397c038fab0e3a917a12d5c5909e901" + integrity sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA== + "@types/parse-json@^4.0.0": version "4.0.0" resolved "https://registry.yarnpkg.com/@types/parse-json/-/parse-json-4.0.0.tgz#2f8bb441434d163b35fb8ffdccd7138927ffb8c0" @@ -1392,6 +1560,14 @@ resolved "https://registry.yarnpkg.com/@xtuc/long/-/long-4.2.2.tgz#d291c6a4e97989b5c61d9acf396ae4fe133a718d" integrity sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ== +JSONStream@^1.3.5: + version "1.3.5" + resolved "https://registry.yarnpkg.com/JSONStream/-/JSONStream-1.3.5.tgz#3208c1f08d3a4d99261ab64f92302bc15e111ca0" + integrity sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ== + dependencies: + jsonparse "^1.2.0" + through ">=2.2.7 <3" + accepts@~1.3.4, accepts@~1.3.5, accepts@~1.3.8: version "1.3.8" resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.8.tgz#0bf0be125b67014adcb0b0921e62db7bffe16b2e" @@ -1447,7 +1623,7 @@ ajv@^6.12.4, ajv@^6.12.5: json-schema-traverse "^0.4.1" uri-js "^4.2.2" -ajv@^8.0.0, ajv@^8.8.0: +ajv@^8.0.0, ajv@^8.11.0, ajv@^8.8.0: version "8.12.0" resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.12.0.tgz#d1a0527323e22f53562c567c00991577dfbe19d1" integrity sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA== @@ -1489,6 +1665,11 @@ anymatch@~3.1.2: normalize-path "^3.0.0" picomatch "^2.0.4" +argparse@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" + integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== + array-flatten@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" @@ -1499,11 +1680,21 @@ array-flatten@^2.1.2: resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-2.1.2.tgz#24ef80a28c1a893617e2149b0c6d0d788293b099" integrity sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ== +array-ify@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/array-ify/-/array-ify-1.0.0.tgz#9e528762b4a9066ad163a6962a364418e9626ece" + integrity sha512-c5AMf34bKdvPhQ7tBGhqkgKNUzMr4WUs+WDtC2ZUGOUncbxKMTvqxYctiseW3+L4bA8ec+GcZ6/A/FW4m8ukng== + array-union@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== +arrify@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" + integrity sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA== + asn1.js@^5.2.0: version "5.4.1" resolved "https://registry.yarnpkg.com/asn1.js/-/asn1.js-5.4.1.tgz#11a980b84ebb91781ce35b0fdc2ee294e3783f07" @@ -1787,6 +1978,20 @@ camel-case@^4.1.1: pascal-case "^3.1.2" tslib "^2.0.3" +camelcase-keys@^6.2.2: + version "6.2.2" + resolved "https://registry.yarnpkg.com/camelcase-keys/-/camelcase-keys-6.2.2.tgz#5e755d6ba51aa223ec7d3d52f25778210f9dc3c0" + integrity sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg== + dependencies: + camelcase "^5.3.1" + map-obj "^4.0.0" + quick-lru "^4.0.1" + +camelcase@^5.3.1: + version "5.3.1" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" + integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== + caniuse-api@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/caniuse-api/-/caniuse-api-3.0.0.tgz#5e4d90e2274961d46291997df599e3ed008ee4c0" @@ -1952,6 +2157,14 @@ commondir@^1.0.1: resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" integrity sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg== +compare-func@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/compare-func/-/compare-func-2.0.0.tgz#fb65e75edbddfd2e568554e8b5b05fff7a51fcb3" + integrity sha512-zHig5N+tPWARooBnb0Zx1MFcdfpyJrfTJ3Y5L+IFvUm8rM74hHz66z0gw0x4tijh5CorKkKUCnW82R2vmpeCRA== + dependencies: + array-ify "^1.0.0" + dot-prop "^5.1.0" + compressible@~2.0.16: version "2.0.18" resolved "https://registry.yarnpkg.com/compressible/-/compressible-2.0.18.tgz#af53cca6b070d4c3c0750fbd77286a6d7cc46fba" @@ -2016,6 +2229,30 @@ content-type@~1.0.4: resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.5.tgz#8b773162656d1d1086784c8f23a54ce6d73d7918" integrity sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA== +conventional-changelog-angular@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/conventional-changelog-angular/-/conventional-changelog-angular-7.0.0.tgz#5eec8edbff15aa9b1680a8dcfbd53e2d7eb2ba7a" + integrity sha512-ROjNchA9LgfNMTTFSIWPzebCwOGFdgkEq45EnvvrmSLvCtAw0HSmrCs7/ty+wAeYUZyNay0YMUNYFTRL72PkBQ== + dependencies: + compare-func "^2.0.0" + +conventional-changelog-conventionalcommits@^7.0.2: + version "7.0.2" + resolved "https://registry.yarnpkg.com/conventional-changelog-conventionalcommits/-/conventional-changelog-conventionalcommits-7.0.2.tgz#aa5da0f1b2543094889e8cf7616ebe1a8f5c70d5" + integrity sha512-NKXYmMR/Hr1DevQegFB4MwfM5Vv0m4UIxKZTTYuD98lpTknaZlSRrDOG4X7wIXpGkfsYxZTghUN+Qq+T0YQI7w== + dependencies: + compare-func "^2.0.0" + +conventional-commits-parser@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/conventional-commits-parser/-/conventional-commits-parser-5.0.0.tgz#57f3594b81ad54d40c1b4280f04554df28627d9a" + integrity sha512-ZPMl0ZJbw74iS9LuX9YIAiW8pfM5p3yh2o/NbXHbkFuZzY5jvdi5jFycEOkmBW5H5I7nA+D6f3UcsCLP2vvSEA== + dependencies: + JSONStream "^1.3.5" + is-text-path "^2.0.0" + meow "^12.0.1" + split2 "^4.0.0" + convert-source-map@^1.7.0: version "1.9.0" resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.9.0.tgz#7faae62353fb4213366d0ca98358d22e8368b05f" @@ -2043,6 +2280,13 @@ core-util-is@~1.0.0: resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85" integrity sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ== +cosmiconfig-typescript-loader@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/cosmiconfig-typescript-loader/-/cosmiconfig-typescript-loader-5.0.0.tgz#0d3becfe022a871f7275ceb2397d692e06045dc8" + integrity sha512-+8cK7jRAReYkMwMiG+bxhcNKiHJDM6bR9FD/nGBXOWdMLuYawjF5cGrtLilJ+LGd3ZjCXnJjR5DkfWPoIVlqJA== + dependencies: + jiti "^1.19.1" + cosmiconfig@^7.0.0: version "7.1.0" resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-7.1.0.tgz#1443b9afa596b670082ea46cbd8f6a62b84635f6" @@ -2054,6 +2298,16 @@ cosmiconfig@^7.0.0: path-type "^4.0.0" yaml "^1.10.0" +cosmiconfig@^8.3.6: + version "8.3.6" + resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-8.3.6.tgz#060a2b871d66dba6c8538ea1118ba1ac16f5fae3" + integrity sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA== + dependencies: + import-fresh "^3.3.0" + js-yaml "^4.1.0" + parse-json "^5.2.0" + path-type "^4.0.0" + create-ecdh@^4.0.0: version "4.0.4" resolved "https://registry.yarnpkg.com/create-ecdh/-/create-ecdh-4.0.4.tgz#d6e7f4bffa66736085a0762fd3a632684dabcc4e" @@ -2222,6 +2476,11 @@ csso@^4.2.0: dependencies: css-tree "^1.1.2" +dargs@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/dargs/-/dargs-7.0.0.tgz#04015c41de0bcb69ec84050f3d9be0caf8d6d5cc" + integrity sha512-2iy1EkLdlBzQGvbweYRFxmFath8+K7+AKB0TlhHWkNuH+TmovaMH/Wp7V7R4u7f4SnX3OgLsU9t1NI9ioDnUpg== + debug@2.6.9: version "2.6.9" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" @@ -2236,6 +2495,19 @@ debug@^4.1.0, debug@^4.1.1: dependencies: ms "2.1.2" +decamelize-keys@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/decamelize-keys/-/decamelize-keys-1.1.1.tgz#04a2d523b2f18d80d0158a43b895d56dff8d19d8" + integrity sha512-WiPxgEirIV0/eIOMcnFBA3/IJZAZqKnwAwWyvvdi4lsr1WCN22nhdf/3db3DoZcUjTV2SqfzIwNyp6y2xs3nmg== + dependencies: + decamelize "^1.1.0" + map-obj "^1.0.0" + +decamelize@^1.1.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" + integrity sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA== + default-gateway@^6.0.3: version "6.0.3" resolved "https://registry.yarnpkg.com/default-gateway/-/default-gateway-6.0.3.tgz#819494c888053bdb743edbf343d6cdf7f2943a71" @@ -2354,6 +2626,13 @@ dot-case@^3.0.4: no-case "^3.0.4" tslib "^2.0.3" +dot-prop@^5.1.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-5.3.0.tgz#90ccce708cd9cd82cc4dc8c3ddd9abdd55b20e88" + integrity sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q== + dependencies: + is-obj "^2.0.0" + dotenv-expand@^5.1.0: version "5.1.0" resolved "https://registry.yarnpkg.com/dotenv-expand/-/dotenv-expand-5.1.0.tgz#3fbaf020bfd794884072ea26b1e9791d45a629f0" @@ -2634,7 +2913,7 @@ find-cache-dir@^3.3.1: make-dir "^3.0.2" pkg-dir "^4.1.0" -find-up@^4.0.0: +find-up@^4.0.0, find-up@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== @@ -2642,10 +2921,18 @@ find-up@^4.0.0: locate-path "^5.0.0" path-exists "^4.0.0" +find-up@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" + integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== + dependencies: + locate-path "^6.0.0" + path-exists "^4.0.0" + follow-redirects@^1.0.0: - version "1.15.2" - resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.2.tgz#b460864144ba63f2681096f274c4e57026da2c13" - integrity sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA== + version "1.15.5" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.5.tgz#54d4d6d062c0fa7d9d17feb008461550e3ba8020" + integrity sha512-vSFWUON1B+yAw1VN4xMfxgn5fTUiaOzAJCKBwIIgT/+7CuGy9+r+5gITvP62j3RmaD5Ph65UaERdOSRGUzZtgw== forwarded@0.2.0: version "0.2.0" @@ -2691,6 +2978,11 @@ function-bind@^1.1.1: resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== +function-bind@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c" + integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== + gensync@^1.0.0-beta.2: version "1.0.0-beta.2" resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0" @@ -2715,6 +3007,17 @@ get-stream@^6.0.0: resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-6.0.1.tgz#a262d8eef67aced57c2852ad6167526a43cbf7b7" integrity sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg== +git-raw-commits@^2.0.11: + version "2.0.11" + resolved "https://registry.yarnpkg.com/git-raw-commits/-/git-raw-commits-2.0.11.tgz#bc3576638071d18655e1cc60d7f524920008d723" + integrity sha512-VnctFhw+xfj8Va1xtfEqCUD2XDrbAPSJx+hSrE5K7fGdjZruW7XV+QOrN7LF/RJyvspRiD2I0asWsxFp0ya26A== + dependencies: + dargs "^7.0.0" + lodash "^4.17.15" + meow "^8.0.0" + split2 "^3.0.0" + through2 "^4.0.0" + glob-parent@^5.1.2, glob-parent@~5.1.2: version "5.1.2" resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" @@ -2739,6 +3042,13 @@ glob@^7.1.3, glob@^7.2.0: once "^1.3.0" path-is-absolute "^1.0.0" +global-dirs@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/global-dirs/-/global-dirs-0.1.1.tgz#b319c0dd4607f353f3be9cca4c72fc148c49f445" + integrity sha512-NknMLn7F2J7aflwFOlGdNIuCDpN3VGoSoB+aap3KABFWbHVn1TCgFC+np23J8W2BiZbjfEw3BFBycSMv1AFblg== + dependencies: + ini "^1.3.4" + globals@^11.1.0: version "11.12.0" resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" @@ -2773,6 +3083,11 @@ handle-thing@^2.0.0: resolved "https://registry.yarnpkg.com/handle-thing/-/handle-thing-2.0.1.tgz#857f79ce359580c340d43081cc648970d0bb234e" integrity sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg== +hard-rejection@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/hard-rejection/-/hard-rejection-2.1.0.tgz#1c6eda5c1685c63942766d79bb40ae773cecd883" + integrity sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA== + has-flag@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" @@ -2817,6 +3132,13 @@ hash.js@^1.0.0, hash.js@^1.0.3: inherits "^2.0.3" minimalistic-assert "^1.0.1" +hasown@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.1.tgz#26f48f039de2c0f8d3356c223fb8d50253519faa" + integrity sha512-1/th4MHjnwncwXsIW6QMzlvYL9kG5e/CpVvLRZe4XPa8TOUNbCELqmvhDmnkNsAjwaG4+I8gJJL0JBvTTLO9qA== + dependencies: + function-bind "^1.1.2" + he@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" @@ -2831,6 +3153,18 @@ hmac-drbg@^1.0.1: minimalistic-assert "^1.0.0" minimalistic-crypto-utils "^1.0.1" +hosted-git-info@^2.1.4: + version "2.8.9" + resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.9.tgz#dffc0bf9a21c02209090f2aa69429e1414daf3f9" + integrity sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw== + +hosted-git-info@^4.0.1: + version "4.1.0" + resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-4.1.0.tgz#827b82867e9ff1c8d0c4d9d53880397d2c86d224" + integrity sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA== + dependencies: + lru-cache "^6.0.0" + hpack.js@^2.1.6: version "2.1.6" resolved "https://registry.yarnpkg.com/hpack.js/-/hpack.js-2.1.6.tgz#87774c0949e513f42e84575b3c45681fade2a0b2" @@ -2940,6 +3274,11 @@ human-signals@^2.1.0: resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0" integrity sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw== +husky@^9.0.11: + version "9.0.11" + resolved "https://registry.yarnpkg.com/husky/-/husky-9.0.11.tgz#fc91df4c756050de41b3e478b2158b87c1e79af9" + integrity sha512-AB6lFlbwwyIqMdHYhwPe+kjOC3Oc5P3nThEoW/AaO2BX3vJDjWPFxYLxokUZOo6RNX20He3AaT8sESs9NJcmEw== + iconv-lite@0.4.24: version "0.4.24" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" @@ -2987,7 +3326,7 @@ immutable@^4.0.0: resolved "https://registry.yarnpkg.com/immutable/-/immutable-4.3.0.tgz#eb1738f14ffb39fd068b1dbe1296117484dd34be" integrity sha512-0AOCmOip+xgJwEVTQj1EfiDDOkPmuyllDuTuEX+DDXUgapLAsBIfkg3sxCYyCEA8mQqZrrxPUGjcOQ2JS3WLkg== -import-fresh@^3.2.1: +import-fresh@^3.0.0, import-fresh@^3.2.1, import-fresh@^3.3.0: version "3.3.0" resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b" integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw== @@ -3003,6 +3342,11 @@ import-local@^3.0.2: pkg-dir "^4.2.0" resolve-cwd "^3.0.0" +indent-string@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251" + integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg== + inflight@^1.0.4: version "1.0.6" resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" @@ -3026,6 +3370,11 @@ inherits@2.0.3: resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" integrity sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw== +ini@^1.3.4: + version "1.3.8" + resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c" + integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew== + interpret@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/interpret/-/interpret-2.2.0.tgz#1a78a0b5965c40a5416d007ad6f50ad27c417df9" @@ -3065,6 +3414,13 @@ is-core-module@^2.11.0: dependencies: has "^1.0.3" +is-core-module@^2.13.0, is-core-module@^2.5.0: + version "2.13.1" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.13.1.tgz#ad0d7532c6fea9da1ebdc82742d74525c6273384" + integrity sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw== + dependencies: + hasown "^2.0.0" + is-docker@^2.0.0, is-docker@^2.1.1: version "2.2.1" resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-2.2.1.tgz#33eeabe23cfe86f14bde4408a02c0cfb853acdaa" @@ -3092,6 +3448,16 @@ is-number@^7.0.0: resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== +is-obj@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-2.0.0.tgz#473fb05d973705e3fd9620545018ca8e22ef4982" + integrity sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w== + +is-plain-obj@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e" + integrity sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg== + is-plain-obj@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-3.0.0.tgz#af6f2ea14ac5a646183a5bbdb5baabbc156ad9d7" @@ -3109,6 +3475,13 @@ is-stream@^2.0.0: resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.1.tgz#fac1e3d53b97ad5a9d0ae9cef2389f5810a5c077" integrity sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg== +is-text-path@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-text-path/-/is-text-path-2.0.0.tgz#b2484e2b720a633feb2e85b67dc193ff72c75636" + integrity sha512-+oDTluR6WEjdXEJMnC2z6A4FRwFoYuvShVVEGsS7ewc0UTi2QtAKMDJuL4BDEVt+5T7MjFo12RP8ghOM75oKJw== + dependencies: + text-extensions "^2.0.0" + is-wsl@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-2.2.0.tgz#74a4c76e77ca9fd3f932f290c17ea326cd157271" @@ -3140,6 +3513,11 @@ jest-worker@^27.4.5: merge-stream "^2.0.0" supports-color "^8.0.0" +jiti@^1.19.1: + version "1.21.0" + resolved "https://registry.yarnpkg.com/jiti/-/jiti-1.21.0.tgz#7c97f8fe045724e136a397f7340475244156105d" + integrity sha512-gFqAIbuKyyso/3G2qhiO2OM6shY6EPP/R0+mkDbyspxKazh8BXDC5FiFsUjlczgdNz/vfra0da2y+aHrusLG/Q== + jquery-ui@^1.13.2: version "1.13.2" resolved "https://registry.yarnpkg.com/jquery-ui/-/jquery-ui-1.13.2.tgz#de03580ae6604773602f8d786ad1abfb75232034" @@ -3157,6 +3535,13 @@ js-tokens@^4.0.0: resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== +js-yaml@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" + integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== + dependencies: + argparse "^2.0.1" + jsesc@^2.5.1: version "2.5.2" resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" @@ -3203,12 +3588,17 @@ jsonfile@^6.0.1: optionalDependencies: graceful-fs "^4.1.6" +jsonparse@^1.2.0: + version "1.3.1" + resolved "https://registry.yarnpkg.com/jsonparse/-/jsonparse-1.3.1.tgz#3f4dae4a91fac315f71062f8521cc239f1366280" + integrity sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg== + junk@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/junk/-/junk-3.1.0.tgz#31499098d902b7e98c5d9b9c80f43457a88abfa1" integrity sha512-pBxcB3LFc8QVgdggvZWyeys+hnrNWg4OcZIU/1X59k5jQdLBlCsYGRQaz234SqoRLTCgMH00fY0xRJH+F9METQ== -kind-of@^6.0.2: +kind-of@^6.0.2, kind-of@^6.0.3: version "6.0.3" resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== @@ -3322,22 +3712,74 @@ locate-path@^5.0.0: dependencies: p-locate "^4.1.0" +locate-path@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286" + integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw== + dependencies: + p-locate "^5.0.0" + +lodash.camelcase@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz#b28aa6288a2b9fc651035c7711f65ab6190331a6" + integrity sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA== + lodash.debounce@^4.0.8: version "4.0.8" resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af" integrity sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow== +lodash.isfunction@^3.0.9: + version "3.0.9" + resolved "https://registry.yarnpkg.com/lodash.isfunction/-/lodash.isfunction-3.0.9.tgz#06de25df4db327ac931981d1bdb067e5af68d051" + integrity sha512-AirXNj15uRIMMPihnkInB4i3NHeb4iBtNg9WRWuK2o31S+ePwwNmDPaTL3o7dTJ+VXNZim7rFs4rxN4YU1oUJw== + +lodash.isplainobject@^4.0.6: + version "4.0.6" + resolved "https://registry.yarnpkg.com/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz#7c526a52d89b45c45cc690b88163be0497f550cb" + integrity sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA== + +lodash.kebabcase@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/lodash.kebabcase/-/lodash.kebabcase-4.1.1.tgz#8489b1cb0d29ff88195cceca448ff6d6cc295c36" + integrity sha512-N8XRTIMMqqDgSy4VLKPnJ/+hpGZN+PHQiJnSenYqPaVV/NCqEogTnAdZLQiGKhxX+JCs8waWq2t1XHWKOmlY8g== + lodash.memoize@^4.1.2: version "4.1.2" resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe" integrity sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag== +lodash.merge@^4.6.2: + version "4.6.2" + resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" + integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== + +lodash.mergewith@^4.6.2: + version "4.6.2" + resolved "https://registry.yarnpkg.com/lodash.mergewith/-/lodash.mergewith-4.6.2.tgz#617121f89ac55f59047c7aec1ccd6654c6590f55" + integrity sha512-GK3g5RPZWTRSeLSpgP8Xhra+pnjBC56q9FZYe1d5RN3TJ35dbkGy3YqBSMbyCrlbi+CM9Z3Jk5yTL7RCsqboyQ== + +lodash.snakecase@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/lodash.snakecase/-/lodash.snakecase-4.1.1.tgz#39d714a35357147837aefd64b5dcbb16becd8f8d" + integrity sha512-QZ1d4xoBHYUeuouhEq3lk3Uq7ldgyFXGBhg04+oRLnIz8o9T65Eh+8YdroUwn846zchkA9yDsDl5CVVaV2nqYw== + +lodash.startcase@^4.4.0: + version "4.4.0" + resolved "https://registry.yarnpkg.com/lodash.startcase/-/lodash.startcase-4.4.0.tgz#9436e34ed26093ed7ffae1936144350915d9add8" + integrity sha512-+WKqsK294HMSc2jEbNgpHpd0JfIBhp7rEV4aqXWqFr6AlXov+SlcgB1Fv01y2kGe3Gc8nMW7VA0SrGuSkRfIEg== + lodash.uniq@^4.5.0: version "4.5.0" resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773" integrity sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ== -lodash@^4.17.21: +lodash.upperfirst@^4.3.1: + version "4.3.1" + resolved "https://registry.yarnpkg.com/lodash.upperfirst/-/lodash.upperfirst-4.3.1.tgz#1365edf431480481ef0d1c68957a5ed99d49f7ce" + integrity sha512-sReKOYJIJf74dhJONhU4e0/shzi1trVbSWDOhKYE5XV2O+H7Sb2Dihwuc7xWxVl+DgFPyTqIN3zMfT9cq5iWDg== + +lodash@^4.17.15, lodash@^4.17.21: version "4.17.21" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== @@ -3370,6 +3812,16 @@ make-dir@^3.0.0, make-dir@^3.0.2, make-dir@^3.1.0: dependencies: semver "^6.0.0" +map-obj@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-1.0.1.tgz#d933ceb9205d82bdcf4886f6742bdc2b4dea146d" + integrity sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg== + +map-obj@^4.0.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-4.3.0.tgz#9304f906e93faae70880da102a9f1df0ea8bb05a" + integrity sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ== + md5.js@^1.3.4: version "1.3.5" resolved "https://registry.yarnpkg.com/md5.js/-/md5.js-1.3.5.tgz#b5d07b8e3216e3e27cd728d72f70d1e6a342005f" @@ -3405,6 +3857,28 @@ memfs@^3.4.3: dependencies: fs-monkey "^1.0.3" +meow@^12.0.1: + version "12.1.1" + resolved "https://registry.yarnpkg.com/meow/-/meow-12.1.1.tgz#e558dddbab12477b69b2e9a2728c327f191bace6" + integrity sha512-BhXM0Au22RwUneMPwSCnyhTOizdWoIEPU9sp0Aqa1PnDMR5Wv2FGXYDjuzJEIX+Eo2Rb8xuYe5jrnm5QowQFkw== + +meow@^8.0.0: + version "8.1.2" + resolved "https://registry.yarnpkg.com/meow/-/meow-8.1.2.tgz#bcbe45bda0ee1729d350c03cffc8395a36c4e897" + integrity sha512-r85E3NdZ+mpYk1C6RjPFEMSE+s1iZMuHtsHAqY0DT3jZczl0diWUZ8g6oU7h0M9cD2EL+PzaYghhCLzR0ZNn5Q== + dependencies: + "@types/minimist" "^1.2.0" + camelcase-keys "^6.2.2" + decamelize-keys "^1.1.0" + hard-rejection "^2.1.0" + minimist-options "4.1.0" + normalize-package-data "^3.0.0" + read-pkg-up "^7.0.1" + redent "^3.0.0" + trim-newlines "^3.0.0" + type-fest "^0.18.0" + yargs-parser "^20.2.3" + merge-descriptors@1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" @@ -3463,6 +3937,11 @@ mimic-fn@^2.1.0: resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== +min-indent@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/min-indent/-/min-indent-1.0.1.tgz#a63f681673b30571fbe8bc25686ae746eefa9869" + integrity sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg== + mini-css-extract-plugin@^1.6.2: version "1.6.2" resolved "https://registry.yarnpkg.com/mini-css-extract-plugin/-/mini-css-extract-plugin-1.6.2.tgz#83172b4fd812f8fc4a09d6f6d16f924f53990ca8" @@ -3489,7 +3968,16 @@ minimatch@^3.1.1: dependencies: brace-expansion "^1.1.7" -minimist@^1.2.0: +minimist-options@4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/minimist-options/-/minimist-options-4.1.0.tgz#c0655713c53a8a2ebd77ffa247d342c40f010619" + integrity sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A== + dependencies: + arrify "^1.0.1" + is-plain-obj "^1.1.0" + kind-of "^6.0.3" + +minimist@^1.2.0, minimist@^1.2.6: version "1.2.8" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== @@ -3591,6 +4079,26 @@ node-releases@^2.0.8: resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.10.tgz#c311ebae3b6a148c89b1813fd7c4d3c024ef537f" integrity sha512-5GFldHPXVG/YZmFzJvKK2zDSzPKhEp0+ZR5SVaoSag9fsL5YgHbUHDfnG5494ISANDcK4KwPXAx2xqVEydmd7w== +normalize-package-data@^2.5.0: + version "2.5.0" + resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8" + integrity sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA== + dependencies: + hosted-git-info "^2.1.4" + resolve "^1.10.0" + semver "2 || 3 || 4 || 5" + validate-npm-package-license "^3.0.1" + +normalize-package-data@^3.0.0: + version "3.0.3" + resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-3.0.3.tgz#dbcc3e2da59509a0983422884cd172eefdfa525e" + integrity sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA== + dependencies: + hosted-git-info "^4.0.1" + is-core-module "^2.5.0" + semver "^7.3.4" + validate-npm-package-license "^3.0.1" + normalize-path@^3.0.0, normalize-path@~3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" @@ -3682,6 +4190,13 @@ p-limit@^2.2.0: dependencies: p-try "^2.0.0" +p-limit@^3.0.2: + version "3.1.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" + integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== + dependencies: + yocto-queue "^0.1.0" + p-locate@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07" @@ -3689,6 +4204,13 @@ p-locate@^4.1.0: dependencies: p-limit "^2.2.0" +p-locate@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834" + integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw== + dependencies: + p-limit "^3.0.2" + p-pipe@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/p-pipe/-/p-pipe-3.1.0.tgz#48b57c922aa2e1af6a6404cb7c6bf0eb9cc8e60e" @@ -3738,7 +4260,7 @@ parse-asn1@^5.0.0, parse-asn1@^5.1.5: pbkdf2 "^3.0.3" safe-buffer "^5.1.1" -parse-json@^5.0.0: +parse-json@^5.0.0, parse-json@^5.2.0: version "5.2.0" resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.2.0.tgz#c76fc66dee54231c962b22bcc8a72cf2f99753cd" integrity sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg== @@ -4160,6 +4682,11 @@ queue-microtask@^1.2.2: resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== +quick-lru@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/quick-lru/-/quick-lru-4.0.1.tgz#5b8878f113a58217848c6482026c73e1ba57727f" + integrity sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g== + randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5, randombytes@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" @@ -4190,6 +4717,34 @@ raw-body@2.5.1: iconv-lite "0.4.24" unpipe "1.0.0" +read-pkg-up@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-7.0.1.tgz#f3a6135758459733ae2b95638056e1854e7ef507" + integrity sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg== + dependencies: + find-up "^4.1.0" + read-pkg "^5.2.0" + type-fest "^0.8.1" + +read-pkg@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-5.2.0.tgz#7bf295438ca5a33e56cd30e053b34ee7250c93cc" + integrity sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg== + dependencies: + "@types/normalize-package-data" "^2.4.0" + normalize-package-data "^2.5.0" + parse-json "^5.0.0" + type-fest "^0.6.0" + +readable-stream@3, readable-stream@^3.0.0, readable-stream@^3.0.6, readable-stream@^3.6.0: + version "3.6.2" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967" + integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA== + dependencies: + inherits "^2.0.3" + string_decoder "^1.1.1" + util-deprecate "^1.0.1" + readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.3.3, readable-stream@^2.3.6: version "2.3.8" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.8.tgz#91125e8042bba1b9887f49345f6277027ce8be9b" @@ -4203,15 +4758,6 @@ readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.3.3, readable string_decoder "~1.1.1" util-deprecate "~1.0.1" -readable-stream@^3.0.6, readable-stream@^3.6.0: - version "3.6.2" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967" - integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA== - dependencies: - inherits "^2.0.3" - string_decoder "^1.1.1" - util-deprecate "^1.0.1" - readdirp@~3.6.0: version "3.6.0" resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" @@ -4226,6 +4772,14 @@ rechoir@^0.7.0: dependencies: resolve "^1.9.0" +redent@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/redent/-/redent-3.0.0.tgz#e557b7998316bb53c9f1f56fa626352c6963059f" + integrity sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg== + dependencies: + indent-string "^4.0.0" + strip-indent "^3.0.0" + regenerate-unicode-properties@^10.1.0: version "10.1.0" resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-10.1.0.tgz#7c3192cab6dd24e21cb4461e5ddd7dd24fa8374c" @@ -4306,15 +4860,22 @@ resolve-cwd@^3.0.0: dependencies: resolve-from "^5.0.0" +resolve-from@5.0.0, resolve-from@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69" + integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw== + resolve-from@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== -resolve-from@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69" - integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw== +resolve-global@1.0.0, resolve-global@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/resolve-global/-/resolve-global-1.0.0.tgz#a2a79df4af2ca3f49bf77ef9ddacd322dad19255" + integrity sha512-zFa12V4OLtT5XUX/Q4VLvTfBf+Ok0SPc1FNGM/z9ctUdiU618qwKpWnd0CHs3+RqROfyEg/DhuHbMWYqcgljEw== + dependencies: + global-dirs "^0.1.1" resolve-url-loader@^5.0.0: version "5.0.0" @@ -4327,6 +4888,15 @@ resolve-url-loader@^5.0.0: postcss "^8.2.14" source-map "0.6.1" +resolve@^1.10.0: + version "1.22.8" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.8.tgz#b6c87a9f2aa06dfab52e3d70ac8cde321fa5a48d" + integrity sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw== + dependencies: + is-core-module "^2.13.0" + path-parse "^1.0.7" + supports-preserve-symlinks-flag "^1.0.0" + resolve@^1.14.2, resolve@^1.9.0: version "1.22.2" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.2.tgz#0ed0943d4e301867955766c9f3e1ae6d01c6845f" @@ -4440,6 +5010,18 @@ selfsigned@^2.1.1: dependencies: node-forge "^1" +"semver@2 || 3 || 4 || 5": + version "5.7.2" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.2.tgz#48d55db737c3287cd4835e17fa13feace1c41ef8" + integrity sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g== + +semver@7.6.0, semver@^7.3.4: + version "7.6.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.0.tgz#1a46a4db4bffcccd97b743b5005c8325f23d4e2d" + integrity sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg== + dependencies: + lru-cache "^6.0.0" + semver@^6.0.0, semver@^6.1.1, semver@^6.1.2, semver@^6.3.0: version "6.3.1" resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" @@ -4604,6 +5186,32 @@ source-map@0.6.1, source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.0, sourc resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== +spdx-correct@^3.0.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.2.0.tgz#4f5ab0668f0059e34f9c00dce331784a12de4e9c" + integrity sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA== + dependencies: + spdx-expression-parse "^3.0.0" + spdx-license-ids "^3.0.0" + +spdx-exceptions@^2.1.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.4.0.tgz#c07a4ede25b16e4f78e6707bbd84b15a45c19c1b" + integrity sha512-hcjppoJ68fhxA/cjbN4T8N6uCUejN8yFw69ttpqtBeCbF3u13n7mb31NB9jKwGTTWWnt9IbRA/mf1FprYS8wfw== + +spdx-expression-parse@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz#cf70f50482eefdc98e3ce0a6833e4a53ceeba679" + integrity sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q== + dependencies: + spdx-exceptions "^2.1.0" + spdx-license-ids "^3.0.0" + +spdx-license-ids@^3.0.0: + version "3.0.17" + resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.17.tgz#887da8aa73218e51a1d917502d79863161a93f9c" + integrity sha512-sh8PWc/ftMqAAdFiBu6Fy6JUOYjqDJBJvIhpfDMyHrr0Rbp5liZqd4TjtQ/RgfLjKFZb+LMx5hpml5qOWy0qvg== + spdy-transport@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/spdy-transport/-/spdy-transport-3.0.0.tgz#00d4863a6400ad75df93361a1608605e5dcdcf31" @@ -4627,6 +5235,18 @@ spdy@^4.0.2: select-hose "^2.0.0" spdy-transport "^3.0.0" +split2@^3.0.0: + version "3.2.2" + resolved "https://registry.yarnpkg.com/split2/-/split2-3.2.2.tgz#bf2cf2a37d838312c249c89206fd7a17dd12365f" + integrity sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg== + dependencies: + readable-stream "^3.0.0" + +split2@^4.0.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/split2/-/split2-4.2.0.tgz#c9c5920904d148bab0b9f67145f245a86aadbfa4" + integrity sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg== + stable@^0.1.8: version "0.1.8" resolved "https://registry.yarnpkg.com/stable/-/stable-0.1.8.tgz#836eb3c8382fe2936feaf544631017ce7d47a3cf" @@ -4701,6 +5321,13 @@ strip-final-newline@^2.0.0: resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad" integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA== +strip-indent@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-3.0.0.tgz#c32e1cee940b6b3432c771bc2c54bcce73cd3001" + integrity sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ== + dependencies: + min-indent "^1.0.0" + style-loader@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/style-loader/-/style-loader-2.0.0.tgz#9669602fd4690740eaaec137799a03addbbc393c" @@ -4791,6 +5418,23 @@ terser@^5.16.5, terser@^5.9.0: commander "^2.20.0" source-map-support "~0.5.20" +text-extensions@^2.0.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/text-extensions/-/text-extensions-2.4.0.tgz#a1cfcc50cf34da41bfd047cc744f804d1680ea34" + integrity sha512-te/NtwBwfiNRLf9Ijqx3T0nlqZiQ2XrrtBvu+cLL8ZRrGkO0NHTug8MYFKyoSrv/sHTaSKfilUkizV6XhxMJ3g== + +through2@^4.0.0: + version "4.0.2" + resolved "https://registry.yarnpkg.com/through2/-/through2-4.0.2.tgz#a7ce3ac2a7a8b0b966c80e7c49f0484c3b239764" + integrity sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw== + dependencies: + readable-stream "3" + +"through@>=2.2.7 <3": + version "2.3.8" + resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" + integrity sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg== + thunky@^1.0.2: version "1.1.0" resolved "https://registry.yarnpkg.com/thunky/-/thunky-1.1.0.tgz#5abaf714a9405db0504732bbccd2cedd9ef9537d" @@ -4825,6 +5469,11 @@ toidentifier@1.0.1: resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35" integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA== +trim-newlines@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-3.0.1.tgz#260a5d962d8b752425b32f3a7db0dcacd176c144" + integrity sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw== + tslib@^2.0.3: version "2.5.0" resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.5.0.tgz#42bfed86f5787aeb41d031866c8f402429e0fddf" @@ -4835,6 +5484,21 @@ tty-browserify@0.0.0: resolved "https://registry.yarnpkg.com/tty-browserify/-/tty-browserify-0.0.0.tgz#a157ba402da24e9bf957f9aa69d524eed42901a6" integrity sha512-JVa5ijo+j/sOoHGjw0sxw734b1LhBkQ3bvUGNdxnVXDCX81Yx7TFgnZygxrIIWn23hbfTaMYLwRmAxFyDuFmIw== +type-fest@^0.18.0: + version "0.18.1" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.18.1.tgz#db4bc151a4a2cf4eebf9add5db75508db6cc841f" + integrity sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw== + +type-fest@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.6.0.tgz#8d2a2370d3df886eb5c90ada1c5bf6188acf838b" + integrity sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg== + +type-fest@^0.8.1: + version "0.8.1" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d" + integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA== + type-is@~1.6.18: version "1.6.18" resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131" @@ -4928,6 +5592,14 @@ uuid@^8.3.0, uuid@^8.3.2: resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== +validate-npm-package-license@^3.0.1: + version "3.0.4" + resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a" + integrity sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew== + dependencies: + spdx-correct "^3.0.0" + spdx-expression-parse "^3.0.0" + vary@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" @@ -5165,11 +5837,29 @@ yaml@^1.10.0, yaml@^1.10.2: resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b" integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg== +yargs-parser@^20.2.3: + version "20.2.9" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee" + integrity sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w== + yargs-parser@^21.1.1: version "21.1.1" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.1.1.tgz#9096bceebf990d21bb31fa9516e0ede294a77d35" integrity sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw== +yargs@^17.0.0: + version "17.7.2" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.7.2.tgz#991df39aca675a192b816e1e0363f9d75d2aa269" + integrity sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w== + dependencies: + cliui "^8.0.1" + escalade "^3.1.1" + get-caller-file "^2.0.5" + require-directory "^2.1.1" + string-width "^4.2.3" + y18n "^5.0.5" + yargs-parser "^21.1.1" + yargs@^17.2.1: version "17.7.1" resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.7.1.tgz#34a77645201d1a8fc5213ace787c220eabbd0967" @@ -5182,3 +5872,8 @@ yargs@^17.2.1: string-width "^4.2.3" y18n "^5.0.5" yargs-parser "^21.1.1" + +yocto-queue@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" + integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==