diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 0000000000..ce07c09196 --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,7 @@ +| Q | A | +|---------------|---------------------------------------------------------------------------------------------------------------------------| +| Branch? | 7.2 for features / 5.4, 6.4, 7.0, and 7.1 for bug fixes | +| Bug fix? | yes/no | +| New feature? | yes/no | +| Deprecations? | yes/no | +| Issues | Fix #... | diff --git a/.github/workflows/cicd-dev.yml b/.github/workflows/cicd-dev.yml index 4e1cad187b..2050f36c59 100644 --- a/.github/workflows/cicd-dev.yml +++ b/.github/workflows/cicd-dev.yml @@ -1,27 +1,8 @@ name: ci/cd-dev -on: - pull_request: - branches: - - develop - types: - - closed - - ready_for_review - - review_requested - - workflow_dispatch: +on: [pull_request] jobs: - CODE_STYLE: - name: PHP-CS-Fixer - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - name: Run PHP-CS-Fixer - uses: erkenes/php-cs-fixer-action@main - with: - args: '--dry-run --diff -vvv' - BUILD: if: github.event.pull_request.merged == true runs-on: ubuntu-latest diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml new file mode 100644 index 0000000000..2053f73465 --- /dev/null +++ b/.github/workflows/tests.yml @@ -0,0 +1,58 @@ +name: tests + +on: + pull_request: + branches: + - develop + +jobs: + CODE_STYLE: + name: CODE STYLE + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Run PHP-CS-Fixer + uses: erkenes/php-cs-fixer-action@main + with: + args: '--dry-run --diff -vvv' + + PHP_UNIT: + name: PHP UNIT + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4.1.1 + + - name: Checkout submodules + run: git submodule update --init --recursive + + - name: Ajustar branch do MultipleLocalAuth + run: cd src/plugins/MultipleLocalAuth && git checkout v3.0.0 + + - name: Inicializar o mapa em modo develop + run: cd dev && docker-compose run -d --service-ports mapas + + - name: Esperar o serviço inicializar + run: sleep 60 + + - name: Instalar os pacotes + run: docker exec -t $(docker-compose -f dev/docker-compose.yml ps -q mapas) composer.phar install + + - name: Criar o arquivo .env na pasta app + run: docker exec -t $(docker-compose -f dev/docker-compose.yml ps -q mapas) cp app/.env.example app/.env + + - name: Configurar o arquivo .env na pasta app + run: docker exec -t $(docker-compose -f dev/docker-compose.yml ps -q mapas) sed -i 's/APP_ENV=/APP_ENV=local/g' app/.env + + - name: Executando as migrations do banco de dados + run: docker exec -t $(docker-compose -f dev/docker-compose.yml ps -q mapas) php app/bin/doctrine migrations:migrate -n + + - name: Executar as fixtures + run: docker exec -t $(docker-compose -f dev/docker-compose.yml ps -q mapas) php app/bin/console app:fixtures + + - name: Executar os testes + uses: php-actions/phpunit@master + with: + version: 10.5 + php_version: 8.2 + bootstrap: vendor/autoload.php + args: app/tests diff --git a/README.md b/README.md index 27c4bde3a4..49041fbc4b 100644 --- a/README.md +++ b/README.md @@ -26,11 +26,12 @@ Agradecemos profundamente a todos que contribuíram até a última versão do pr - [Nova Arquitetura](./app/README.md) de arquivos e diretórios - [Conexão](./app/README.md) com o Banco de Dados - [Como colaborar](./help/CREATE-ISSUES.md) criando issues -- [Como implementar](./app/CREATE-PULL-REQUESTS.md) novos códigos através de pull requests +- [Como implementar](./help/CREATE-PULL-REQUESTS.md) novos códigos através de pull requests +- [Fluxo](./help/DEV-FLOW.md) de Desenvolvimento ## Tecnologias -- PHP7^ +- PHP8.1^ - Symfony packages - Slim packages - Doctrine diff --git a/app/.env.example b/app/.env.example new file mode 100644 index 0000000000..14bde28f4a --- /dev/null +++ b/app/.env.example @@ -0,0 +1 @@ +APP_ENV= \ No newline at end of file diff --git a/app/.gitignore b/app/.gitignore index a725465aee..b44d4ebbd0 100644 --- a/app/.gitignore +++ b/app/.gitignore @@ -1 +1,2 @@ -vendor/ \ No newline at end of file +vendor/ +.env \ No newline at end of file diff --git a/app/README.md b/app/README.md index ad91a2d668..def20c2bce 100644 --- a/app/README.md +++ b/app/README.md @@ -278,6 +278,43 @@ public function __construct() --- +## Migrations +Migrations são a forma (correta) de fazer um versionamento do banco de dados, nesta parte da aplicação isso é fornecido pela biblioteca `doctrine/migrations` mas no core do MapaCultural isso ainda é feito por uma decisão técnica interna chamada `db-updates.php` + +
+Como criar uma nova migration + +#### Passo 1 - Criar uma nova classe no diretório `/app/migrations` + +```php +addSql('CREATE TABLE ...'); + } + + public function down(Schema $schema): void + { + //$this->addSql('DROP TABLE ...'); + } +} +``` + +Note que o nome da classe deve informar o momento de sua criação, para que seja mantida uma sequencia temporal da evolução do esquema do banco de dados. + +> Documentação oficial das migrations do Doctrine: +
+ ## Command Comandos são entradas via CLI (linha de comando) que permitem automatizar alguns processos, como rodar testes, veririfcar estilo de código, e debugar rotas @@ -388,7 +425,7 @@ Para criar um no cenário de teste funcional, basta adicionar sua nova classe no ```php Console Comma --- +## DI (Injeção de dependência) +Com a injeção de dependência diminuímos o acoplamento das nossas classes. E a razão para isso ser tão importante está no princípio da inversão de dependência em que o código deve depender de abstrações e não de implementações concretas. + +Documentação PHP-DI: https://php-di.org + +Todo o código se encontra no diretório `/app/config`, no arquivo `di.php`. + ## Console Commands +
+CACHE CLEAR + +### Limpar cache +Para executar o comando de limpar cache basta entrar no container da aplicação e executar o seguinte comando: + +```shell +php app/bin/console cache:clear +``` + +
+ +
+COMMAND SQL + +### Executar código SQL +Para executar um comando SQL basta entrar no container da aplicação e executar o seguinte comando: + +```shell +php app/bin/console database:sql {sql} +``` +O argumento chamado de `sql` é requerido e é o comando a ser executar no banco de dados. +
TESTS @@ -451,11 +518,36 @@ php app/bin/console app:code-style :memo: Fixtures são dados falsos com a finalidade de testes. +#### Configuração do ambiente + +Antes de executar os fixtures, é necessário criar um arquivo `.env` dentro da pasta app (/app/.env). Este arquivo deve conter a configuração de ambiente necessária. Um arquivo de exemplo chamado `.env.example` foi fornecido para facilitar esse processo. + +1. Copie o arquivo `.env.example` para `.env`: + + ```sh + cp .env.example .env + ``` + +2. Abra o arquivo `.env` e configure as variáveis de ambiente. Para fins de desenvolvimento, você pode definir a variável `APP_ENV` como `local`: + + ```sh + APP_ENV=local + ``` + + +#### Executando os Fixtures + Para executar o conjunto de fixtures basta entrar no container da aplicação e executar ``` php app/bin/console app:fixtures ``` +> **Observação:** +> Se o arquivo `.env` não for encontrado, você verá a seguinte mensagem de erro: +> +> ```sh +> Please create a .env file in the root directory (/app/.env) +> ```
diff --git a/app/bin/console b/app/bin/console index d05eae7193..2d08198b51 100644 --- a/app/bin/console +++ b/app/bin/console @@ -4,22 +4,38 @@ require dirname(__DIR__, 2).'/vendor/autoload.php'; require dirname(__DIR__, 2).'/public/bootstrap.php'; +use App\Application\Environment; +use App\Command\ClearCacheCommand; use App\Command\CodeStyleCommand; +use App\Command\DatabaseCommand; use App\Command\DebugRouterCommand; use App\Command\FixturesCommand; use App\Command\TestsCommand; use App\Command\WelcomeCommand; use Symfony\Component\Console\Application; +use Symfony\Component\Dotenv\Dotenv; +use Symfony\Component\Filesystem\Filesystem; + +$env = Environment::getEnvData(); +$dotenv = new Dotenv(); +$dotenv->load($env); $application = new Application(); $entityManager = $app->em ?? null; $application->addCommands([ - new WelcomeCommand(), - new TestsCommand(), + new ClearCacheCommand(new Filesystem()), new CodeStyleCommand(), - new FixturesCommand($entityManager), new DebugRouterCommand(), + new TestsCommand(), + new WelcomeCommand(), ]); +if (true === Environment::isLocal()) { + $application->addCommands([ + new DatabaseCommand(), + new FixturesCommand($entityManager) + ]); +} + $application->run(); diff --git a/app/bin/doctrine b/app/bin/doctrine index 0d26b7e51d..32c0ed0b1f 100644 --- a/app/bin/doctrine +++ b/app/bin/doctrine @@ -4,14 +4,64 @@ require dirname(__DIR__, 2).'/vendor/autoload.php'; require dirname(__DIR__, 2).'/public/bootstrap.php'; +use App\Application\Environment; +use Doctrine\Migrations\Configuration\Configuration as MigrationsConfiguration; +use Doctrine\Migrations\Configuration\EntityManager\ExistingEntityManager; +use Doctrine\Migrations\Configuration\Migration\ExistingConfiguration; +use Doctrine\Migrations\DependencyFactory; +use Doctrine\Migrations\Metadata\Storage\TableMetadataStorageConfiguration; +use Doctrine\Migrations\Tools\Console\Command as MigrationsCommand; use Doctrine\ORM\Tools\Console\ConsoleRunner; use Doctrine\ORM\Tools\Console\EntityManagerProvider\SingleManagerProvider; +use Doctrine\ORM\Tools\Console\Command\SchemaTool; $entityManager = $app->em ?? null; -$commands = []; +$application = ConsoleRunner::createApplication( + new SingleManagerProvider($entityManager) +); + +$configuration = new MigrationsConfiguration(); +$configuration->addMigrationsDirectory( + 'App\Migrations', + './app/migrations' +); +$configuration->setAllOrNothing(true); +$configuration->setCheckDatabasePlatform(false); + +$storageConfiguration = new TableMetadataStorageConfiguration(); +$storageConfiguration->setTableName('doctrine_migration_versions'); +$configuration->setMetadataStorageConfiguration($storageConfiguration); -ConsoleRunner::run( - new SingleManagerProvider($entityManager), - $commands +$dependencyFactory = DependencyFactory::fromEntityManager( + new ExistingConfiguration($configuration), + new ExistingEntityManager($entityManager) ); + +$application->setCatchExceptions(true); + +$application->addCommands([ + new MigrationsCommand\CurrentCommand($dependencyFactory), + new MigrationsCommand\DiffCommand($dependencyFactory), + new MigrationsCommand\DumpSchemaCommand($dependencyFactory), + new MigrationsCommand\ExecuteCommand($dependencyFactory), + new MigrationsCommand\GenerateCommand($dependencyFactory), + new MigrationsCommand\LatestCommand($dependencyFactory), + new MigrationsCommand\ListCommand($dependencyFactory), + new MigrationsCommand\MigrateCommand($dependencyFactory), + new MigrationsCommand\RollupCommand($dependencyFactory), + new MigrationsCommand\StatusCommand($dependencyFactory), + new MigrationsCommand\SyncMetadataCommand($dependencyFactory), + new MigrationsCommand\UpToDateCommand($dependencyFactory), + new MigrationsCommand\VersionCommand($dependencyFactory), +]); + +if (true === Environment::isLocal()) { + $application->addCommands([ + new SchemaTool\UpdateCommand(), + new SchemaTool\CreateCommand(), + new SchemaTool\DropCommand(), + ]); +} + +$application->run(); diff --git a/app/config/di.php b/app/config/di.php new file mode 100644 index 0000000000..74b676134e --- /dev/null +++ b/app/config/di.php @@ -0,0 +1,76 @@ + fn () => new Serializer([new ObjectNormalizer()]), + ValidatorInterface::class => fn () => Validation::createValidatorBuilder()->enableAttributeMapping()->getValidator(), + ...repositories(), + ...services(), +]; + +function repositories(): array +{ + return [ + AgentRepositoryInterface::class => fn () => new AgentRepository(), + EventRepositoryInterface::class => fn () => new EventRepository(), + OpportunityRepositoryInterface::class => fn () => new OpportunityRepository(), + ProjectRepositoryInterface::class => fn () => new ProjectRepository(), + SealRepositoryInterface::class => fn () => new SealRepository(), + SpaceRepositoryInterface::class => fn () => new SpaceRepository(), + TermRepositoryInterface::class => fn () => new TermRepository(), + UserRepositoryInterface::class => fn () => new UserRepository(), + ]; +} + +function services(): array +{ + return [ + AgentServiceInterface::class => fn () => new AgentService(new AgentRepository(), new UserRepository(), new Serializer([new ObjectNormalizer()])), + EventServiceInterface::class => fn () => new EventService(new EventRepository(), new Serializer([new ObjectNormalizer()])), + OpportunityServiceInterface::class => fn () => new OpportunityService(new OpportunityRepository(), new Serializer([new ObjectNormalizer()])), + ProjectServiceInterface::class => fn () => new ProjectService(new ProjectRepository(), new Serializer([new ObjectNormalizer()])), + SealServiceInterface::class => fn () => new SealService(new AgentRepository(), new SealRepository(), new Serializer([new ObjectNormalizer()])), + SpaceServiceInterface::class => fn () => new SpaceService(new Serializer([new ObjectNormalizer()]), new SpaceRepository()), + TermServiceInterface::class => fn () => new TermService(new Serializer([new ObjectNormalizer()]), new TermRepository()), + UserServiceInterface::class => fn () => new UserService(new UserRepository()), + ]; +} diff --git a/app/migrations/.gitignore b/app/migrations/.gitignore new file mode 100755 index 0000000000..e69de29bb2 diff --git a/app/migrations/Version20240710125659.php b/app/migrations/Version20240710125659.php new file mode 100644 index 0000000000..483c0b4d5c --- /dev/null +++ b/app/migrations/Version20240710125659.php @@ -0,0 +1,26 @@ +addSql('ALTER TABLE usr ADD COLUMN auth_token VARCHAR(255) NULL;'); + } + + public function down(Schema $schema): void + { + $this->addSql('ALTER TABLE usr DROP COLUMN auth_token;'); + } +} diff --git a/app/migrations/Version20240716230312.php b/app/migrations/Version20240716230312.php new file mode 100644 index 0000000000..4f2bc4f86a --- /dev/null +++ b/app/migrations/Version20240716230312.php @@ -0,0 +1,32 @@ +addSql('ALTER TABLE usr DROP COLUMN auth_token'); + } + + public function up(Schema $schema): void + { + $this->addSql('ALTER TABLE usr ADD COLUMN auth_token TEXT NULL;'); + } + + public function down(Schema $schema): void + { + $this->addSql('ALTER TABLE usr DROP COLUMN auth_token'); + $this->addSql('ALTER TABLE usr ADD auth_token VARCHAR(255) NULL;'); + } +} diff --git a/app/routes/api/agent.php b/app/routes/api/agent.php index 746f8414a5..02833c2c23 100644 --- a/app/routes/api/agent.php +++ b/app/routes/api/agent.php @@ -17,7 +17,7 @@ '/api/v2/agents/{id}' => [ Request::METHOD_GET => [AgentApiController::class, 'getOne'], Request::METHOD_PATCH => [AgentApiController::class, 'patch'], - Request::METHOD_DELETE => [AgentApiController::class, 'delete'], + Request::METHOD_DELETE => [AgentApiController::class, 'remove'], ], '/api/v2/agents/{id}/opportunities' => [ Request::METHOD_GET => [OpportunityApiController::class, 'getOpportunitiesByAgent'], diff --git a/app/routes/api/auth.php b/app/routes/api/auth.php new file mode 100644 index 0000000000..3222289ce7 --- /dev/null +++ b/app/routes/api/auth.php @@ -0,0 +1,12 @@ + [ + Request::METHOD_POST => [AuthApiController::class, 'auth'], + ], +]; diff --git a/app/routes/api/event.php b/app/routes/api/event.php index b898c66ebb..b5c526e545 100644 --- a/app/routes/api/event.php +++ b/app/routes/api/event.php @@ -16,6 +16,6 @@ '/api/v2/events/{id}' => [ Request::METHOD_GET => [EventApiController::class, 'getOne'], Request::METHOD_PATCH => [EventApiController::class, 'patch'], - Request::METHOD_DELETE => [EventApiController::class, 'delete'], + Request::METHOD_DELETE => [EventApiController::class, 'remove'], ], ]; diff --git a/app/routes/api/opportunity.php b/app/routes/api/opportunity.php index 792474eddd..02c77273ca 100644 --- a/app/routes/api/opportunity.php +++ b/app/routes/api/opportunity.php @@ -13,6 +13,6 @@ '/api/v2/opportunities/{id}' => [ Request::METHOD_GET => [OpportunityApiController::class, 'getOne'], Request::METHOD_PATCH => [OpportunityApiController::class, 'patch'], - Request::METHOD_DELETE => [OpportunityApiController::class, 'delete'], + Request::METHOD_DELETE => [OpportunityApiController::class, 'remove'], ], ]; diff --git a/app/routes/api/project.php b/app/routes/api/project.php index 4b6a364e22..cbe34db1b9 100644 --- a/app/routes/api/project.php +++ b/app/routes/api/project.php @@ -13,6 +13,6 @@ '/api/v2/projects/{id}' => [ Request::METHOD_GET => [ProjectApiController::class, 'getOne'], Request::METHOD_PATCH => [ProjectApiController::class, 'patch'], - Request::METHOD_DELETE => [ProjectApiController::class, 'delete'], + Request::METHOD_DELETE => [ProjectApiController::class, 'remove'], ], ]; diff --git a/app/routes/api/seal.php b/app/routes/api/seal.php index e26ea1230e..f287452b53 100644 --- a/app/routes/api/seal.php +++ b/app/routes/api/seal.php @@ -13,6 +13,6 @@ '/api/v2/seals/{id}' => [ Request::METHOD_GET => [SealApiController::class, 'getOne'], Request::METHOD_PATCH => [SealApiController::class, 'patch'], - Request::METHOD_DELETE => [SealApiController::class, 'delete'], + Request::METHOD_DELETE => [SealApiController::class, 'remove'], ], ]; diff --git a/app/routes/api/space.php b/app/routes/api/space.php index 1da6f78424..6bb18dc768 100644 --- a/app/routes/api/space.php +++ b/app/routes/api/space.php @@ -13,7 +13,7 @@ ], '/api/v2/spaces/{id}' => [ Request::METHOD_GET => [SpaceApiController::class, 'getOne'], - Request::METHOD_DELETE => [SpaceApiController::class, 'delete'], + Request::METHOD_DELETE => [SpaceApiController::class, 'remove'], Request::METHOD_PATCH => [SpaceApiController::class, 'patch'], ], '/api/v2/spaces/{id}/events' => [ diff --git a/app/routes/api/term.php b/app/routes/api/term.php index eaff38fd31..31e83fae96 100644 --- a/app/routes/api/term.php +++ b/app/routes/api/term.php @@ -8,8 +8,11 @@ return [ '/api/v2/terms' => [ Request::METHOD_GET => [TermApiController::class, 'getList'], + Request::METHOD_POST => [TermApiController::class, 'post'], ], '/api/v2/terms/{id}' => [ Request::METHOD_GET => [TermApiController::class, 'getOne'], + Request::METHOD_PATCH => [TermApiController::class, 'patch'], + Request::METHOD_DELETE => [TermApiController::class, 'remove'], ], ]; diff --git a/app/src/Application/Environment.php b/app/src/Application/Environment.php new file mode 100644 index 0000000000..e3f7fab79c --- /dev/null +++ b/app/src/Application/Environment.php @@ -0,0 +1,46 @@ +load(self::getEnvData()); + + return self::LOCAL === self::getEnvinronment(); + } +} diff --git a/app/src/Command/ClearCacheCommand.php b/app/src/Command/ClearCacheCommand.php new file mode 100644 index 0000000000..12c38a00b0 --- /dev/null +++ b/app/src/Command/ClearCacheCommand.php @@ -0,0 +1,58 @@ +writeln([ + PHP_EOL, + '=================================', + '=== CLEARING CACHE ', + '=================================', + PHP_EOL, + ]); + + foreach (self::DIRECTORIES as $directory) { + $this->clearDirectory($directory); + } + + return Command::SUCCESS; + } + + private function clearDirectory(string $directory): void + { + if (false === $this->filesystem->exists($directory)) { + return; + } + + $finder = new Finder(); + $finder->files()->in($directory); + + foreach ($finder as $file) { + $this->filesystem->remove($file->getRealPath()); + } + } +} diff --git a/app/src/Command/DatabaseCommand.php b/app/src/Command/DatabaseCommand.php new file mode 100644 index 0000000000..4b350e35cc --- /dev/null +++ b/app/src/Command/DatabaseCommand.php @@ -0,0 +1,29 @@ +writeln('-------------------------------------------------------'); + passthru(sprintf('php app/bin/doctrine dbal:run-sql "%s"', $input->getArgument('sql'))); + + return Command::SUCCESS; + } + + protected function configure(): void + { + $this->addArgument('sql', InputArgument::OPTIONAL, 'The code SQL'); + $this->setDescription('The code SQL.'); + } +} diff --git a/app/src/Command/FixturesCommand.php b/app/src/Command/FixturesCommand.php index 1b2a4ca3d6..f6b0ec6b66 100644 --- a/app/src/Command/FixturesCommand.php +++ b/app/src/Command/FixturesCommand.php @@ -25,10 +25,8 @@ protected function execute(InputInterface $input, OutputInterface $output): int { $output->writeLn([ PHP_EOL, - '==============================', - '== RUN DATA FIXTURES ==', - '==============================', - PHP_EOL, + '=================================', + '=== RUNNING DATA FIXTURES ', ]); $loader = new Loader(); @@ -37,6 +35,12 @@ protected function execute(InputInterface $input, OutputInterface $output): int $executor = new ORMExecutor($this->entityManager, new ORMPurger()); $executor->execute($loader->getFixtures(), true); + $output->writeln([ + '=== '.count($loader->getFixtures()).' fixtures executed', + '=================================', + PHP_EOL, + ]); + return Command::SUCCESS; } diff --git a/app/src/Command/TestsCommand.php b/app/src/Command/TestsCommand.php index 6f81d48d2b..c8438c8afa 100644 --- a/app/src/Command/TestsCommand.php +++ b/app/src/Command/TestsCommand.php @@ -16,7 +16,8 @@ class TestsCommand extends Command protected function execute(InputInterface $input, OutputInterface $output): int { $output->writeln('-------------------------------------------------------'); - passthru("php vendor/bin/phpunit {$input->getArgument('path')}"); + passthru('php app/bin/console app:fixtures'); + passthru("php vendor/bin/phpunit {$input->getArgument('path')} --testdox --colors=always"); $output->writeln('-------------------------------------------------------'); return Command::SUCCESS; diff --git a/app/src/Controller/Api/AbstractApiController.php b/app/src/Controller/Api/AbstractApiController.php new file mode 100644 index 0000000000..12aaf0f171 --- /dev/null +++ b/app/src/Controller/Api/AbstractApiController.php @@ -0,0 +1,19 @@ +repository = new AgentRepository(); - - $this->agentService = new AgentService(); - $this->agentRequest = new AgentRequest(); + public function __construct( + private readonly AgentRepositoryInterface $repository, + private readonly AgentServiceInterface $agentService, + private readonly AgentRequest $agentRequest + ) { } public function getList(): JsonResponse @@ -36,63 +29,55 @@ public function getList(): JsonResponse public function getOne(array $params): JsonResponse { - $agent = $this->repository->find((int) $params['id']); + $id = $this->extractIdParam($params); - return new JsonResponse($agent); + return new JsonResponse( + $this->repository->find($id) + ); } public function getTypes(): JsonResponse { - $types = $this->agentService->getTypes(); - - return new JsonResponse($types); + return new JsonResponse( + $this->agentService->getTypes() + ); } public function post(): JsonResponse { - try { - $agentData = $this->agentRequest->validatePost(); - - $agent = $this->agentService->create((object) $agentData); - - $responseData = [ - 'id' => $agent->getId(), - 'name' => $agent->getName(), - 'shortDescription' => $agent->getShortDescription(), - 'terms' => $agent->getTerms(), - 'type' => $agent->getType(), - ]; - - return new JsonResponse($responseData, Response::HTTP_CREATED); - } catch (Exception $exception) { - return new JsonResponse(['error' => $exception->getMessage()], Response::HTTP_BAD_REQUEST); + $agentData = $this->agentRequest->validatePost(); + + if (true === empty($agentData['name'])) { + throw new FieldRequiredException('name'); } + + $agent = $this->agentService->create((object) $agentData); + + $responseData = [ + 'id' => $agent->getId(), + 'name' => $agent->getName(), + 'shortDescription' => $agent->getShortDescription(), + 'terms' => $agent->getTerms(), + 'type' => $agent->getType(), + ]; + + return new JsonResponse($responseData, Response::HTTP_CREATED); } public function patch(array $params): JsonResponse { - try { - $agentData = $this->agentRequest->validateUpdate(); - $agent = $this->agentService->update((int) $params['id'], (object) $agentData); - - return new JsonResponse($agent, Response::HTTP_CREATED); - } catch (ResourceNotFoundException $exception) { - return new JsonResponse(['error' => $exception->getMessage()], Response::HTTP_NOT_FOUND); - } catch (Exception $exception) { - return new JsonResponse(['error' => $exception->getMessage()], Response::HTTP_BAD_REQUEST); - } + $id = $this->extractIdParam($params); + $agentData = $this->agentRequest->validateUpdate(); + $agent = $this->agentService->update($id, (object) $agentData); + + return new JsonResponse($agent, Response::HTTP_CREATED); } - public function delete(array $params): JsonResponse + public function remove(array $params): JsonResponse { - try { - $this->agentService->discard((int) $params['id']); - - return new JsonResponse(status: Response::HTTP_NO_CONTENT); - } catch (ResourceNotFoundException $exception) { - return new JsonResponse(['error' => $exception->getMessage()], Response::HTTP_NOT_FOUND); - } catch (Exception $exception) { - return new JsonResponse(['error' => $exception->getMessage()], Response::HTTP_BAD_REQUEST); - } + $id = $this->extractIdParam($params); + $this->agentService->removeById($id); + + return new JsonResponse(status: Response::HTTP_NO_CONTENT); } } diff --git a/app/src/Controller/Api/AuthApiController.php b/app/src/Controller/Api/AuthApiController.php new file mode 100644 index 0000000000..7f4009b308 --- /dev/null +++ b/app/src/Controller/Api/AuthApiController.php @@ -0,0 +1,52 @@ +authRequest->validatePost(); + + $user = $this->userService->findOneBy([ + 'email' => $request['email'], + ]); + + if (null === $user->getMetadata('localAuthenticationPassword')) { + throw new InvalidCredentialsException(); + } + + if (false === password_verify($request['password'], $user->getMetadata('localAuthenticationPassword'))) { + throw new InvalidCredentialsException(); + } + + $payload = [ + 'email' => $request['email'], + ]; + $jwt = JWT::encode($payload, Environment::getApiPrivateKey(), 'RS256'); + + $user->setAuthToken($jwt); + $this->userService->save($user); + + return new JsonResponse([ + 'id' => $user->id, + 'name' => $user->profile->name, + 'token' => $user->getAuthToken(), + ]); + } +} diff --git a/app/src/Controller/Api/EventApiController.php b/app/src/Controller/Api/EventApiController.php index da193e9403..05ceb7d9e2 100644 --- a/app/src/Controller/Api/EventApiController.php +++ b/app/src/Controller/Api/EventApiController.php @@ -4,26 +4,19 @@ namespace App\Controller\Api; -use App\Repository\EventRepository; +use App\Repository\Interface\EventRepositoryInterface; use App\Request\EventRequest; -use App\Service\EventService; -use Exception; +use App\Service\Interface\EventServiceInterface; use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\HttpFoundation\Response; -class EventApiController +class EventApiController extends AbstractApiController { - private EventService $eventService; - private EventRepository $repository; - private EventRequest $eventRequest; - - public function __construct() - { - $this->eventService = new EventService(); - - $this->repository = new EventRepository(); - - $this->eventRequest = new EventRequest(); + public function __construct( + private readonly EventRepositoryInterface $repository, + private readonly EventServiceInterface $eventService, + private readonly EventRequest $eventRequest + ) { } public function getList(): JsonResponse @@ -35,7 +28,8 @@ public function getList(): JsonResponse public function getOne(array $params): JsonResponse { - $event = $this->repository->find((int) $params['id']); + $id = $this->extractIdParam($params); + $event = $this->repository->find($id); return new JsonResponse($event); } @@ -49,53 +43,34 @@ public function getTypes(): JsonResponse public function getEventsBySpace(array $params): JsonResponse { - $events = $this->repository->findEventsBySpaceId((int) $params['id']); + $id = $this->extractIdParam($params); + $events = $this->repository->findEventsBySpaceId($id); return new JsonResponse($events); } public function post(): JsonResponse { - try { - $eventData = $this->eventRequest->validatePost(); - - $event = $this->eventService->create((object) $eventData); - - $responseData = [ - 'id' => $event->getId(), - 'name' => $event->getName(), - 'shortDescription' => $event->getShortDescription(), - 'classificacaoEtaria' => $event->getMetadata('classificacaoEtaria'), - 'terms' => $event->getTerms(), - ]; - - return new JsonResponse($responseData, Response::HTTP_CREATED); - } catch (Exception $exception) { - return new JsonResponse(['error' => $exception->getMessage()], Response::HTTP_BAD_REQUEST); - } + $eventData = $this->eventRequest->validatePost(); + $event = $this->eventService->create((object) $eventData); + + return new JsonResponse($event, Response::HTTP_CREATED); } public function patch(array $params): JsonResponse { - try { - $eventData = $this->eventRequest->validateUpdate(); - $event = $this->eventService->update((int) $params['id'], (object) $eventData); - - return new JsonResponse($event, Response::HTTP_CREATED); - } catch (Exception $exception) { - return new JsonResponse(['error' => $exception->getMessage()], Response::HTTP_BAD_REQUEST); - } + $id = $this->extractIdParam($params); + $eventData = $this->eventRequest->validateUpdate(); + $event = $this->eventService->update($id, (object) $eventData); + + return new JsonResponse($event, Response::HTTP_OK); } - public function delete($params): JsonResponse + public function remove(array $params): JsonResponse { - try { - $event = $this->eventRequest->validateEventExistent($params); - $this->repository->softDelete($event); - - return new JsonResponse([], Response::HTTP_OK); - } catch (Exception $exception) { - return new JsonResponse(['error' => $exception->getMessage()], Response::HTTP_BAD_REQUEST); - } + $id = $this->extractIdParam($params); + $this->eventService->removeById($id); + + return new JsonResponse(status: Response::HTTP_NO_CONTENT); } } diff --git a/app/src/Controller/Api/OpportunityApiController.php b/app/src/Controller/Api/OpportunityApiController.php index e7c82399df..95905cb3aa 100644 --- a/app/src/Controller/Api/OpportunityApiController.php +++ b/app/src/Controller/Api/OpportunityApiController.php @@ -4,24 +4,19 @@ namespace App\Controller\Api; -use App\Repository\OpportunityRepository; +use App\Repository\Interface\OpportunityRepositoryInterface; use App\Request\OpportunityRequest; -use App\Service\OpportunityService; -use Exception; +use App\Service\Interface\OpportunityServiceInterface; use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\HttpFoundation\Response; -class OpportunityApiController +class OpportunityApiController extends AbstractApiController { - private OpportunityRequest $opportunityRequest; - private OpportunityService $opportunityService; - private OpportunityRepository $repository; - - public function __construct() - { - $this->repository = new OpportunityRepository(); - $this->opportunityRequest = new OpportunityRequest(); - $this->opportunityService = new OpportunityService(); + public function __construct( + private readonly OpportunityRepositoryInterface $repository, + private readonly OpportunityServiceInterface $opportunityService, + private readonly OpportunityRequest $opportunityRequest + ) { } public function getList(): JsonResponse @@ -33,33 +28,30 @@ public function getList(): JsonResponse public function getOne(array $params): JsonResponse { - $opportunity = $this->repository->find((int) $params['id']); + $id = $this->extractIdParam($params); + $opportunity = $this->repository->find($id); return new JsonResponse($opportunity); } public function post(): JsonResponse { - try { - $opportunityData = $this->opportunityRequest->validatePost(); - $opportunity = $this->opportunityService->create((object) $opportunityData); - - $responseData = [ - 'id' => $opportunity->getId(), - 'name' => $opportunity->getName(), - 'terms' => $opportunity->getTerms(), - '_type' => $opportunity->getType(), - ]; - - return new JsonResponse($responseData, Response::HTTP_CREATED); - } catch (Exception $exception) { - return new JsonResponse(['error' => $exception->getMessage()], Response::HTTP_BAD_REQUEST); - } + $opportunityData = $this->opportunityRequest->validatePost(); + $opportunity = $this->opportunityService->create((object) $opportunityData); + + $responseData = [ + 'id' => $opportunity->getId(), + 'name' => $opportunity->getName(), + 'terms' => $opportunity->getTerms(), + '_type' => $opportunity->getType(), + ]; + + return new JsonResponse($responseData, Response::HTTP_CREATED); } public function getOpportunitiesByAgent(array $params): JsonResponse { - $agentId = (int) $params['id']; + $agentId = $this->extractIdParam($params); $opportunities = $this->repository->findOpportunitiesByAgentId($agentId); return new JsonResponse($opportunities); @@ -67,25 +59,18 @@ public function getOpportunitiesByAgent(array $params): JsonResponse public function patch(array $params): JsonResponse { - try { - $opportunityData = $this->opportunityRequest->validateUpdate(); - $opportunity = $this->opportunityService->update((int) $params['id'], (object) $opportunityData); - - return new JsonResponse($opportunity, Response::HTTP_CREATED); - } catch (Exception $exception) { - return new JsonResponse(['error' => $exception->getMessage()], Response::HTTP_BAD_REQUEST); - } + $id = $this->extractIdParam($params); + $opportunityData = $this->opportunityRequest->validateUpdate(); + $opportunity = $this->opportunityService->update($id, (object) $opportunityData); + + return new JsonResponse($opportunity, Response::HTTP_CREATED); } - public function delete(array $params): JsonResponse + public function remove(array $params): JsonResponse { - try { - $opportunity = $this->opportunityRequest->validateDelete($params); - $this->repository->softDelete($opportunity); - - return new JsonResponse([], Response::HTTP_NO_CONTENT); - } catch (Exception $exception) { - return new JsonResponse(['error' => $exception->getMessage()], Response::HTTP_BAD_REQUEST); - } + $id = $this->extractIdParam($params); + $this->opportunityService->removeById($id); + + return new JsonResponse(status: Response::HTTP_NO_CONTENT); } } diff --git a/app/src/Controller/Api/ProjectApiController.php b/app/src/Controller/Api/ProjectApiController.php index b77f9b7cc2..c3f4b7cdae 100644 --- a/app/src/Controller/Api/ProjectApiController.php +++ b/app/src/Controller/Api/ProjectApiController.php @@ -4,27 +4,19 @@ namespace App\Controller\Api; -use App\Exception\ResourceNotFoundException; -use App\Repository\ProjectRepository; +use App\Repository\Interface\ProjectRepositoryInterface; use App\Request\ProjectRequest; -use App\Service\ProjectService; -use Exception; +use App\Service\Interface\ProjectServiceInterface; use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\HttpFoundation\Response; -class ProjectApiController +class ProjectApiController extends AbstractApiController { - public ProjectService $projectService; - private ProjectRequest $projectRequest; - - private ProjectRepository $repository; - - public function __construct() - { - $this->repository = new ProjectRepository(); - - $this->projectService = new ProjectService(); - $this->projectRequest = new ProjectRequest(); + public function __construct( + private readonly ProjectRepositoryInterface $repository, + private readonly ProjectServiceInterface $projectService, + private readonly ProjectRequest $projectRequest + ) { } public function getList(): JsonResponse @@ -36,54 +28,42 @@ public function getList(): JsonResponse public function getOne(array $params): JsonResponse { - $project = $this->repository->find((int) $params['id']); + $id = $this->extractIdParam($params); + $project = $this->repository->find($id); return new JsonResponse($project); } public function post(): JsonResponse { - try { - $projectData = $this->projectRequest->validatePost(); - - $project = $this->projectService->create((object) $projectData); - - $responseData = [ - 'id' => $project->getId(), - 'name' => $project->getName(), - 'shortDescription' => $project->getShortDescription(), - 'type' => $project->getType(), - ]; - - return new JsonResponse($responseData, status: Response::HTTP_CREATED); - } catch (Exception $exception) { - return new JsonResponse(['error' => $exception->getMessage()], status: Response::HTTP_BAD_REQUEST); - } + $projectData = $this->projectRequest->validatePost(); + + $project = $this->projectService->create((object) $projectData); + + $responseData = [ + 'id' => $project->getId(), + 'name' => $project->getName(), + 'shortDescription' => $project->getShortDescription(), + 'type' => $project->getType(), + ]; + + return new JsonResponse($responseData, status: Response::HTTP_CREATED); } public function patch(array $params): JsonResponse { - try { - $projectData = $this->projectRequest->validateUpdate(); + $id = $this->extractIdParam($params); + $projectData = $this->projectRequest->validateUpdate(); + $project = $this->projectService->update($id, (object) $projectData); - $project = $this->projectService->update((int) $params['id'], (object) $projectData); - - return new JsonResponse($project, Response::HTTP_CREATED); - } catch (Exception $exception) { - return new JsonResponse(['error' => $exception->getMessage()], Response::HTTP_BAD_REQUEST); - } + return new JsonResponse($project, Response::HTTP_CREATED); } - public function delete(array $params): JsonResponse + public function remove(array $params): JsonResponse { - try { - $this->projectService->discard((int) $params['id']); - - return new JsonResponse(status: Response::HTTP_NO_CONTENT); - } catch (ResourceNotFoundException $exception) { - return new JsonResponse(['error' => $exception->getMessage()], Response::HTTP_NOT_FOUND); - } catch (Exception $exception) { - return new JsonResponse(['error' => $exception->getMessage()], Response::HTTP_BAD_REQUEST); - } + $id = $this->extractIdParam($params); + $this->projectService->removeById($id); + + return new JsonResponse(status: Response::HTTP_NO_CONTENT); } } diff --git a/app/src/Controller/Api/SealApiController.php b/app/src/Controller/Api/SealApiController.php index 7cf6adbee4..5bc44bc7c8 100644 --- a/app/src/Controller/Api/SealApiController.php +++ b/app/src/Controller/Api/SealApiController.php @@ -4,27 +4,19 @@ namespace App\Controller\Api; -use App\Exception\ResourceNotFoundException; -use App\Exception\ValidatorException; -use App\Repository\SealRepository; +use App\Repository\Interface\SealRepositoryInterface; use App\Request\SealRequest; -use App\Service\SealService; -use Exception; -use InvalidArgumentException; +use App\Service\Interface\SealServiceInterface; use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\HttpFoundation\Response; -class SealApiController +class SealApiController extends AbstractApiController { - private SealRepository $repository; - private SealService $sealService; - private SealRequest $sealRequest; - - public function __construct() - { - $this->repository = new SealRepository(); - $this->sealService = new SealService(); - $this->sealRequest = new SealRequest(); + public function __construct( + private readonly SealRepositoryInterface $repository, + private readonly SealServiceInterface $sealService, + private readonly SealRequest $sealRequest + ) { } public function getList(): JsonResponse @@ -36,55 +28,34 @@ public function getList(): JsonResponse public function getOne(array $params): JsonResponse { - $seal = $this->repository->find((int) $params['id']); + $id = $this->extractIdParam($params); + $seal = $this->repository->find($id); return new JsonResponse($seal); } public function post(): JsonResponse { - try { - $sealData = $this->sealRequest->validatePost(); - $seal = $this->sealService->create($sealData); + $sealData = $this->sealRequest->validatePost(); + $seal = $this->sealService->create($sealData); - return new JsonResponse($seal, Response::HTTP_CREATED); - } catch (ValidatorException $exception) { - return new JsonResponse([ - 'error' => $exception->getMessage(), - 'fields' => $exception->getFields(), - ], Response::HTTP_BAD_REQUEST); - } catch (InvalidArgumentException $exception) { - return new JsonResponse(['error' => $exception->getMessage()], Response::HTTP_BAD_REQUEST); - } + return new JsonResponse($seal, Response::HTTP_CREATED); } public function patch(array $params): JsonResponse { - try { - $sealData = $this->sealRequest->validatePatch(); - $seal = $this->sealService->update((int) $params['id'], (object) $sealData); + $id = $this->extractIdParam($params); + $sealData = $this->sealRequest->validatePatch(); + $seal = $this->sealService->update($id, (object) $sealData); - return new JsonResponse($seal, Response::HTTP_CREATED); - } catch (ResourceNotFoundException $exception) { - return new JsonResponse(['error' => $exception->getMessage()], Response::HTTP_NOT_FOUND); - } catch (ValidatorException $exception) { - return new JsonResponse([ - 'error' => $exception->getMessage(), - 'fields' => $exception->getFields(), - ], Response::HTTP_BAD_REQUEST); - } catch (Exception $exception) { - return new JsonResponse(['error' => $exception->getMessage()], Response::HTTP_BAD_REQUEST); - } + return new JsonResponse($seal, Response::HTTP_CREATED); } - public function delete(array $params): JsonResponse + public function remove(array $params): JsonResponse { - try { - $this->sealService->delete((int) $params['id']); + $id = $this->extractIdParam($params); + $this->sealService->removeById($id); - return new JsonResponse(null, Response::HTTP_NO_CONTENT); - } catch (ResourceNotFoundException $exception) { - return new JsonResponse(['error' => $exception->getMessage()], Response::HTTP_NOT_FOUND); - } + return new JsonResponse(status: Response::HTTP_NO_CONTENT); } } diff --git a/app/src/Controller/Api/SpaceApiController.php b/app/src/Controller/Api/SpaceApiController.php index fb4a6b6f4b..2101154ff4 100644 --- a/app/src/Controller/Api/SpaceApiController.php +++ b/app/src/Controller/Api/SpaceApiController.php @@ -4,26 +4,21 @@ namespace App\Controller\Api; -use App\Enum\EntityStatusEnum; -use App\Exception\ResourceNotFoundException; -use App\Repository\SpaceRepository; +use App\Exception\FieldInvalidException; +use App\Exception\FieldRequiredException; +use App\Repository\Interface\SpaceRepositoryInterface; use App\Request\SpaceRequest; -use App\Service\SpaceService; -use Exception; +use App\Service\Interface\SpaceServiceInterface; use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\HttpFoundation\Response; -class SpaceApiController +class SpaceApiController extends AbstractApiController { - private SpaceRepository $repository; - private SpaceRequest $spaceRequest; - private SpaceService $spaceService; - - public function __construct() - { - $this->repository = new SpaceRepository(); - $this->spaceRequest = new SpaceRequest(); - $this->spaceService = new SpaceService(); + public function __construct( + private readonly SpaceRepositoryInterface $repository, + private readonly SpaceServiceInterface $spaceService, + private readonly SpaceRequest $spaceRequest + ) { } public function getList(): JsonResponse @@ -35,55 +30,60 @@ public function getList(): JsonResponse public function getOne(array $params): JsonResponse { - $space = $this->repository->find((int) $params['id']); + $id = $this->extractIdParam($params); + $space = $this->repository->find($id); return new JsonResponse($space); } public function post(): JsonResponse { - try { - $spaceData = $this->spaceRequest->validatePost(); - $space = $this->spaceService->create((object) $spaceData); - - $responseData = [ - 'id' => $space->getId(), - 'name' => $space->getName(), - 'shortDescription' => $space->getShortDescription(), - 'terms' => $space->getTerms(), - 'type' => $space->getType(), - ]; - - return new JsonResponse($responseData, Response::HTTP_CREATED); - } catch (Exception $exception) { - return new JsonResponse(['error' => $exception->getMessage()], Response::HTTP_BAD_REQUEST); + $spaceData = $this->spaceRequest->validatePost(); + + if (true === empty($spaceData['name'])) { + throw new FieldRequiredException('name'); } - } - public function patch(array $params): JsonResponse - { - try { - $spaceData = $this->spaceRequest->validateUpdate(); - $space = $this->spaceService->update((int) $params['id'], (object) $spaceData); - - return new JsonResponse($space, Response::HTTP_CREATED); - } catch (ResourceNotFoundException $exception) { - return new JsonResponse(['error' => $exception->getMessage()], Response::HTTP_NOT_FOUND); - } catch (Exception $exception) { - return new JsonResponse(['error' => $exception->getMessage()], Response::HTTP_BAD_REQUEST); + if (false === is_string($spaceData['name'])) { + throw new FieldInvalidException('name'); } + + $space = $this->spaceService->create((object) $spaceData); + + $responseData = [ + 'id' => $space->getId(), + 'name' => $space->getName(), + 'shortDescription' => $space->getShortDescription(), + 'terms' => $space->getTerms(), + 'type' => $space->getType(), + ]; + + return new JsonResponse($responseData, Response::HTTP_CREATED); } - public function delete(array $params): JsonResponse + public function patch(array $params): JsonResponse { - $space = $this->repository->find((int) $params['id']); + $id = $this->extractIdParam($params); + $spaceData = $this->spaceRequest->validateUpdate(); + + if (true === empty($spaceData['name'])) { + throw new FieldRequiredException('name'); + } - if (EntityStatusEnum::TRASH->getValue() === $space->status) { - return new JsonResponse(['error' => 'Espaço não encontrado'], Response::HTTP_NOT_FOUND); + if (false === is_string($spaceData['name'])) { + throw new FieldInvalidException('name'); } - $this->repository->softDelete($space); + $space = $this->spaceService->update($id, (object) $spaceData); + + return new JsonResponse($space, Response::HTTP_CREATED); + } + + public function remove(array $params): JsonResponse + { + $id = $this->extractIdParam($params); + $this->spaceService->removeById($id); - return new JsonResponse(null, Response::HTTP_NO_CONTENT); + return new JsonResponse(status: Response::HTTP_NO_CONTENT); } } diff --git a/app/src/Controller/Api/TermApiController.php b/app/src/Controller/Api/TermApiController.php index 004ca40def..cfaced5081 100644 --- a/app/src/Controller/Api/TermApiController.php +++ b/app/src/Controller/Api/TermApiController.php @@ -4,16 +4,19 @@ namespace App\Controller\Api; -use App\Repository\TermRepository; +use App\Repository\Interface\TermRepositoryInterface; +use App\Request\TermRequest; +use App\Service\Interface\TermServiceInterface; use Symfony\Component\HttpFoundation\JsonResponse; +use Symfony\Component\HttpFoundation\Response; -class TermApiController +class TermApiController extends AbstractApiController { - private TermRepository $repository; - - public function __construct() - { - $this->repository = new TermRepository(); + public function __construct( + private readonly TermRepositoryInterface $repository, + private readonly TermRequest $termRequest, + private readonly TermServiceInterface $service + ) { } public function getList(): JsonResponse @@ -25,8 +28,34 @@ public function getList(): JsonResponse public function getOne(array $params): JsonResponse { - $term = $this->repository->find((int) $params['id']); + $id = $this->extractIdParam($params); + $term = $this->repository->find($id); return new JsonResponse($term); } + + public function post(): JsonResponse + { + $termData = $this->termRequest->validatePost(); + $term = $this->service->create($termData); + + return new JsonResponse($term, Response::HTTP_CREATED); + } + + public function patch(array $params): JsonResponse + { + $id = $this->extractIdParam($params); + $termData = $this->termRequest->validatePatch(); + $term = $this->service->update($id, $termData); + + return new JsonResponse($term, Response::HTTP_OK); + } + + public function remove(array $params): JsonResponse + { + $id = $this->extractIdParam($params); + $this->service->removeById($id); + + return new JsonResponse(status: Response::HTTP_NO_CONTENT); + } } diff --git a/app/src/DTO/AuthDto.php b/app/src/DTO/AuthDto.php new file mode 100644 index 0000000000..a13b38b29e --- /dev/null +++ b/app/src/DTO/AuthDto.php @@ -0,0 +1,18 @@ + 2])], groups: ['patch', 'post'])] + public mixed $name; + + #[Sequentially([new NotBlank()], groups: ['post'])] + #[Sequentially([new Type('string'), new Length(['min' => 2])], groups: ['patch', 'post'])] + public mixed $shortDescription; + + #[Sequentially([new NotBlank()], groups: ['post'])] + #[Sequentially([new Type('string'), new Length(['min' => 2])], groups: ['patch', 'post'])] + public mixed $classificacaoEtaria; + + #[Sequentially( + constraints: [ + new NotBlank(groups: ['post']), + new Collection( + fields: [ + 'linguagem' => [ + new NotBlank(groups: ['post']), + new Type(type: 'array', groups: ['post', 'patch']), + new All([ + new Type(type: 'string', groups: ['post', 'patch']), + ]), + new Count(min: 1, groups: ['post', 'patch']), + ], + 'tag' => [ + new Optional([ + new Type(type: 'array', groups: ['post', 'patch']), + new All([ + new Type(type: 'string', groups: ['post', 'patch']), + ]), + ], groups: ['post', 'patch']), + ], + ], + groups: ['post', 'patch'], + allowExtraFields: false + ), + ], + groups: ['post', 'patch'] + )] + public mixed $terms; +} diff --git a/app/src/DTO/TermDto.php b/app/src/DTO/TermDto.php new file mode 100644 index 0000000000..91be9eda56 --- /dev/null +++ b/app/src/DTO/TermDto.php @@ -0,0 +1,27 @@ + 2])], groups: ['patch', 'post'])] + public mixed $taxonomy; + + #[Sequentially([new NotBlank()], groups: ['post'])] + #[Sequentially([new Type('string'), new Length(['min' => 2]), new UniqueInEntity(Term::class, 'term')], groups: ['patch', 'post'])] + public mixed $term; + + #[Sequentially([new NotBlank()], groups: ['post'])] + #[Sequentially([new Type('string'), new Length(['min' => 2])], groups: ['patch', 'post'])] + public mixed $description; +} diff --git a/app/src/DataFixtures/AgentFixtures.php b/app/src/DataFixtures/AgentFixtures.php index 5bc16bc022..ad2fc894d5 100644 --- a/app/src/DataFixtures/AgentFixtures.php +++ b/app/src/DataFixtures/AgentFixtures.php @@ -94,6 +94,9 @@ public function load(ObjectManager $manager): void $this->setReference(sprintf('%s-%s', self::AGENT_ID_PREFIX, $agentData['id']), $agent); $manager->persist($agent); + + $this->setProperty($user, 'profile', $agent); + $manager->persist($user); } $manager->flush(); diff --git a/app/src/DataFixtures/OpportunityFixtures.php b/app/src/DataFixtures/OpportunityFixtures.php index 2668afb05c..44fd333505 100644 --- a/app/src/DataFixtures/OpportunityFixtures.php +++ b/app/src/DataFixtures/OpportunityFixtures.php @@ -19,7 +19,7 @@ class OpportunityFixtures extends Fixture implements DependentFixtureInterface public const OPPORTUNITY_ID_3 = 3; public const OPPORTUNITY_ID_4 = 4; - public const EVENT_OPPORTUNITTIES = [ + public const EVENT_OPPORTUNITIES = [ [ 'id' => self::OPPORTUNITY_ID_1, 'name' => 'Concurso Teste', @@ -33,6 +33,7 @@ class OpportunityFixtures extends Fixture implements DependentFixtureInterface 'Artes', 'Teste', ], + 'type' => 23, ], [ 'id' => self::OPPORTUNITY_ID_2, @@ -47,10 +48,11 @@ class OpportunityFixtures extends Fixture implements DependentFixtureInterface 'Artes', 'Teste', ], + 'type' => 23, ], ]; - public const PROJECT_OPPORTUNITTIES = [ + public const PROJECT_OPPORTUNITIES = [ [ 'id' => self::OPPORTUNITY_ID_3, 'name' => 'Projeto de Verão', @@ -64,6 +66,7 @@ class OpportunityFixtures extends Fixture implements DependentFixtureInterface 'Artes', 'Teste', ], + 'type' => 24, ], [ 'id' => self::OPPORTUNITY_ID_4, @@ -78,6 +81,7 @@ class OpportunityFixtures extends Fixture implements DependentFixtureInterface 'Artes', 'Teste', ], + 'type' => 24, ], ]; @@ -98,7 +102,7 @@ public function load(ObjectManager $manager): void $event = $this->getReference(EventFixtures::EVENT_ID_PREFIX.'-'.EventFixtures::EVENT_ID_1); $project = $this->getReference(ProjectFixtures::PROJECT_ID_PREFIX.'-'.ProjectFixtures::PROJECT_ID_3); - foreach (self::EVENT_OPPORTUNITTIES as $opportunityData) { + foreach (self::EVENT_OPPORTUNITIES as $opportunityData) { /** @var EventOpportunity $opportunity */ $opportunity = $this->getSerializer()->denormalize($opportunityData, EventOpportunity::class); $opportunity->setRegistrationTo(new DateTime()); @@ -111,7 +115,7 @@ public function load(ObjectManager $manager): void $manager->persist($opportunity); } - foreach (self::PROJECT_OPPORTUNITTIES as $opportunityData) { + foreach (self::PROJECT_OPPORTUNITIES as $opportunityData) { /** @var ProjectOpportunity $opportunity */ $opportunity = $this->getSerializer()->denormalize($opportunityData, ProjectOpportunity::class); $opportunity->setRegistrationTo(new DateTime()); diff --git a/app/src/Entity/Term.php b/app/src/Entity/Term.php new file mode 100644 index 0000000000..7efdd2fcec --- /dev/null +++ b/app/src/Entity/Term.php @@ -0,0 +1,65 @@ +id; + } + + public function getTaxonomy(): string + { + return $this->taxonomy; + } + + public function setTaxonomy(string $taxonomy): void + { + $this->taxonomy = $taxonomy; + } + + public function getTerm(): string + { + return $this->term; + } + + public function setTerm(string $term): void + { + $this->term = $term; + } + + public function getDescription(): ?string + { + return $this->description; + } + + public function setDescription(?string $description): void + { + $this->description = $description; + } +} diff --git a/app/src/Exception/InvalidCredentialsException.php b/app/src/Exception/InvalidCredentialsException.php new file mode 100644 index 0000000000..a107c3e1ae --- /dev/null +++ b/app/src/Exception/InvalidCredentialsException.php @@ -0,0 +1,13 @@ +routes, $context); $this->dispatchAction($matcher); - } catch (MethodNotAllowedException $exception) { + } catch (MethodNotAllowedException) { (new JsonResponse([ 'error' => 'Method not allowed: '.$_SERVER['REQUEST_METHOD'], ], status: Response::HTTP_METHOD_NOT_ALLOWED))->send(); exit; - } catch (ResourceNotFoundException $exception) { + } catch (ResourceNotFoundException) { return; } } @@ -58,7 +67,26 @@ private function dispatchAction(UrlMatcher $matcher): void unset($parameters['_route']); - $response = (new $controller())->$method($parameters); + $builder = new ContainerBuilder(); + $builder->addDefinitions(dirname(__DIR__).'/config/di.php'); + $container = $builder->build(); + + $controller = $container->get($controller); + + try { + $response = $controller->$method($parameters); + } catch (InternalResourceNotFoundException $exception) { + $response = new JsonResponse(['error' => $exception->getMessage()], Response::HTTP_NOT_FOUND); + } catch (ValidatorException $exception) { + $response = new JsonResponse([ + 'error' => $exception->getMessage(), + 'fields' => $exception->getFields(), + ], Response::HTTP_BAD_REQUEST); + } catch (FieldInvalidException|FieldRequiredException|RequiredIdParamException|InvalidRequestException $exception) { + $response = new JsonResponse(['error' => $exception->getMessage()], Response::HTTP_BAD_REQUEST); + } catch (Exception|Error $exception) { + $response = new JsonResponse(['error' => $exception->getMessage()], Response::HTTP_BAD_REQUEST); + } if ($response instanceof Response) { $response->send(); diff --git a/app/src/Repository/AgentRepository.php b/app/src/Repository/AgentRepository.php index ab53c0a1ea..c8328178bf 100644 --- a/app/src/Repository/AgentRepository.php +++ b/app/src/Repository/AgentRepository.php @@ -5,10 +5,12 @@ namespace App\Repository; use App\Enum\EntityStatusEnum; +use App\Exception\ResourceNotFoundException; +use App\Repository\Interface\AgentRepositoryInterface; use Doctrine\Persistence\ObjectRepository; use MapasCulturais\Entities\Agent; -class AgentRepository extends AbstractRepository +class AgentRepository extends AbstractRepository implements AgentRepositoryInterface { private ObjectRepository $repository; @@ -22,13 +24,24 @@ public function findAll(): array { return $this->repository ->createQueryBuilder('agent') + ->where('agent.status = :status') + ->setParameter('status', EntityStatusEnum::ENABLED->getValue()) ->getQuery() ->getArrayResult(); } - public function find(int $id): ?Agent + public function find(int $id): Agent { - return $this->repository->find($id); + $agent = $this->repository->findOneBy([ + 'id' => $id, + 'status' => EntityStatusEnum::ENABLED->getValue(), + ]); + + if (null === $agent) { + throw new ResourceNotFoundException(); + } + + return $agent; } public function save(Agent $agent): void @@ -37,7 +50,7 @@ public function save(Agent $agent): void $this->mapaCulturalEntityManager->flush(); } - public function softDelete(Agent $agent): void + public function remove(Agent $agent): void { $agent->setStatus(EntityStatusEnum::TRASH->getValue()); $this->mapaCulturalEntityManager->persist($agent); diff --git a/app/src/Repository/EventRepository.php b/app/src/Repository/EventRepository.php index 7da1da0838..e65f1149fb 100644 --- a/app/src/Repository/EventRepository.php +++ b/app/src/Repository/EventRepository.php @@ -5,11 +5,13 @@ namespace App\Repository; use App\Enum\EntityStatusEnum; +use App\Exception\ResourceNotFoundException; +use App\Repository\Interface\EventRepositoryInterface; use Doctrine\Persistence\ObjectRepository; use MapasCulturais\Entities\Event; use MapasCulturais\Entities\EventOccurrence; -class EventRepository extends AbstractRepository +class EventRepository extends AbstractRepository implements EventRepositoryInterface { private ObjectRepository $repository; @@ -23,18 +25,29 @@ public function findAll(): array { return $this->repository ->createQueryBuilder('events') + ->where('events.status = :status') + ->setParameter('status', EntityStatusEnum::ENABLED->getValue()) ->getQuery() ->getArrayResult(); } - public function find(int $id): ?Event + public function find(int $id): Event { - return $this->repository->find($id); + $event = $this->repository->findOneBy([ + 'id' => $id, + 'status' => EntityStatusEnum::ENABLED->getValue(), + ]); + + if (null === $event) { + throw new ResourceNotFoundException(); + } + + return $event; } public function findEventsBySpaceId(int $spaceId): array { - $queryBuilder = $this->getEntityManager() + $queryBuilder = $this->entityManager ->createQueryBuilder() ->select([ 'e.id', @@ -61,10 +74,11 @@ public function save($event): void $event->save(); } - public function softDelete(Event $event): void + public function remove(Event $event): void { $event->setStatus(EntityStatusEnum::TRASH->getValue()); - $this->save($event); + $this->mapaCulturalEntityManager->persist($event); + $this->mapaCulturalEntityManager->flush(); } public function update(Event $event): void diff --git a/app/src/Repository/Interface/AgentRepositoryInterface.php b/app/src/Repository/Interface/AgentRepositoryInterface.php new file mode 100644 index 0000000000..2ab51e6e1e --- /dev/null +++ b/app/src/Repository/Interface/AgentRepositoryInterface.php @@ -0,0 +1,18 @@ +repository ->createQueryBuilder('opportunity') + ->where('opportunity.status = :status') + ->setParameter('status', EntityStatusEnum::ENABLED->getValue()) ->getQuery() ->getArrayResult(); } - public function find(int $id): ?Opportunity + public function find(int $id): Opportunity { - return $this->repository->find($id); + $opportunity = $this->repository->findOneBy([ + 'id' => $id, + 'status' => EntityStatusEnum::ENABLED, + ]); + + if (null === $opportunity) { + throw new ResourceNotFoundException(); + } + + return $opportunity; } public function save(Opportunity $opportunity): void @@ -40,20 +52,22 @@ public function save(Opportunity $opportunity): void public function findOpportunitiesByAgentId(int $agentId): array { - $queryBuilder = $this->getEntityManager() - ->createQueryBuilder() - ->select('ao') - ->from(AgentOpportunity::class, 'ao') - ->where('ao.ownerEntity = :agentId') - ->andWhere('ao.parent is null') - ->setParameter('agentId', $agentId); - - return $queryBuilder->getQuery()->getArrayResult(); + return $this->repository + ->createQueryBuilder('opportunity') + ->where('opportunity.status = :status') + ->andWhere('opportunity.owner = :agent') + ->setParameters([ + 'status' => EntityStatusEnum::ENABLED->getValue(), + 'agent' => $agentId, + ]) + ->getQuery() + ->getArrayResult(); } - public function softDelete(Opportunity $opportunity): void + public function remove(Opportunity $opportunity): void { $opportunity->setStatus(EntityStatusEnum::TRASH->getValue()); - $this->save($opportunity); + $this->mapaCulturalEntityManager->persist($opportunity); + $this->mapaCulturalEntityManager->flush(); } } diff --git a/app/src/Repository/ProjectRepository.php b/app/src/Repository/ProjectRepository.php index 5564604477..f6cde719a1 100644 --- a/app/src/Repository/ProjectRepository.php +++ b/app/src/Repository/ProjectRepository.php @@ -5,10 +5,12 @@ namespace App\Repository; use App\Enum\EntityStatusEnum; +use App\Exception\ResourceNotFoundException; +use App\Repository\Interface\ProjectRepositoryInterface; use Doctrine\Persistence\ObjectRepository; use MapasCulturais\Entities\Project; -class ProjectRepository extends AbstractRepository +class ProjectRepository extends AbstractRepository implements ProjectRepositoryInterface { private ObjectRepository $repository; @@ -22,13 +24,24 @@ public function findAll(): array { return $this->repository ->createQueryBuilder('project') + ->where('project.status = :status') + ->setParameter('status', EntityStatusEnum::ENABLED->getValue()) ->getQuery() ->getArrayResult(); } - public function find(int $id): ?Project + public function find(int $id): Project { - return $this->repository->find($id); + $project = $this->repository->findOneBy([ + 'id' => $id, + 'status' => EntityStatusEnum::ENABLED->getValue(), + ]); + + if (null === $project) { + throw new ResourceNotFoundException(); + } + + return $project; } public function save(Project $project): void @@ -37,7 +50,7 @@ public function save(Project $project): void $this->mapaCulturalEntityManager->flush(); } - public function softDelete(Project $project): void + public function remove(Project $project): void { $project->setStatus(EntityStatusEnum::TRASH->getValue()); $this->mapaCulturalEntityManager->persist($project); diff --git a/app/src/Repository/SealRepository.php b/app/src/Repository/SealRepository.php index 6c45495905..bd46758d4b 100644 --- a/app/src/Repository/SealRepository.php +++ b/app/src/Repository/SealRepository.php @@ -5,10 +5,12 @@ namespace App\Repository; use App\Enum\EntityStatusEnum; +use App\Exception\ResourceNotFoundException; +use App\Repository\Interface\SealRepositoryInterface; use Doctrine\Persistence\ObjectRepository; use MapasCulturais\Entities\Seal; -class SealRepository extends AbstractRepository +class SealRepository extends AbstractRepository implements SealRepositoryInterface { private ObjectRepository $repository; @@ -23,13 +25,24 @@ public function findAll(): array { return $this->repository ->createQueryBuilder('seal') + ->where('seal.status = :status') + ->setParameter('status', EntityStatusEnum::ENABLED->getValue()) ->getQuery() ->getArrayResult(); } - public function find(int $id): ?Seal + public function find(int $id): Seal { - return $this->repository->find($id); + $seal = $this->repository->findOneBy([ + 'id' => $id, + 'status' => EntityStatusEnum::ENABLED->getValue(), + ]); + + if (null === $seal) { + throw new ResourceNotFoundException(); + } + + return $seal; } public function save(Seal $seal): void @@ -38,10 +51,10 @@ public function save(Seal $seal): void $this->mapaCulturalEntityManager->flush(); } - public function softDelete(Seal $space): void + public function remove(Seal $seal): void { - $space->setStatus(EntityStatusEnum::TRASH->getValue()); - $this->mapaCulturalEntityManager->persist($space); + $seal->setStatus(EntityStatusEnum::TRASH->getValue()); + $this->mapaCulturalEntityManager->persist($seal); $this->mapaCulturalEntityManager->flush(); } } diff --git a/app/src/Repository/SpaceRepository.php b/app/src/Repository/SpaceRepository.php index 618682db4a..b78e83a107 100644 --- a/app/src/Repository/SpaceRepository.php +++ b/app/src/Repository/SpaceRepository.php @@ -5,10 +5,12 @@ namespace App\Repository; use App\Enum\EntityStatusEnum; +use App\Exception\ResourceNotFoundException; +use App\Repository\Interface\SpaceRepositoryInterface; use Doctrine\Persistence\ObjectRepository; use MapasCulturais\Entities\Space; -class SpaceRepository extends AbstractRepository +class SpaceRepository extends AbstractRepository implements SpaceRepositoryInterface { private ObjectRepository $repository; @@ -30,16 +32,27 @@ public function findAll(): array { return $this->repository ->createQueryBuilder('space') + ->where('space.status = :status') + ->setParameter('status', EntityStatusEnum::ENABLED->getValue()) ->getQuery() ->getArrayResult(); } - public function find(int $id): ?Space + public function find(int $id): Space { - return $this->repository->find($id); + $space = $this->repository->findOneBy([ + 'id' => $id, + 'status' => EntityStatusEnum::ENABLED->getValue(), + ]); + + if (null === $space) { + throw new ResourceNotFoundException(); + } + + return $space; } - public function softDelete(Space $space): void + public function remove(Space $space): void { $space->setStatus(EntityStatusEnum::TRASH->getValue()); $this->mapaCulturalEntityManager->persist($space); diff --git a/app/src/Repository/TermRepository.php b/app/src/Repository/TermRepository.php index de211d6c63..7bc8b95931 100644 --- a/app/src/Repository/TermRepository.php +++ b/app/src/Repository/TermRepository.php @@ -4,10 +4,12 @@ namespace App\Repository; +use App\Exception\ResourceNotFoundException; +use App\Repository\Interface\TermRepositoryInterface; use Doctrine\Persistence\ObjectRepository; use MapasCulturais\Entities\Term; -class TermRepository extends AbstractRepository +class TermRepository extends AbstractRepository implements TermRepositoryInterface { private ObjectRepository $repository; @@ -26,9 +28,17 @@ public function findAll(): array ->getArrayResult(); } - public function find(int $id): ?Term + public function find(int $id): Term { - return $this->repository->find($id); + $term = $this->repository->findOneBy([ + 'id' => $id, + ]); + + if (null === $term) { + throw new ResourceNotFoundException(); + } + + return $term; } public function save(Term $term): void @@ -36,4 +46,10 @@ public function save(Term $term): void $this->mapaCulturalEntityManager->persist($term); $this->mapaCulturalEntityManager->flush(); } + + public function remove(Term $term): void + { + $this->mapaCulturalEntityManager->remove($term); + $this->mapaCulturalEntityManager->flush(); + } } diff --git a/app/src/Repository/UserRepository.php b/app/src/Repository/UserRepository.php new file mode 100644 index 0000000000..9030479bba --- /dev/null +++ b/app/src/Repository/UserRepository.php @@ -0,0 +1,72 @@ +repository = $this->mapaCulturalEntityManager->getRepository(User::class); + } + + public function findAll(): array + { + return $this->repository + ->createQueryBuilder('user') + ->where('User.status = :status') + ->setParameter('status', EntityStatusEnum::ENABLED->getValue()) + ->getQuery() + ->getArrayResult(); + } + + public function getUserMetadata(int $userId): mixed + { + return $this->mapaCulturalEntityManager + ->getRepository(UserMeta::class) + ->findOneBy(['owner' => $userId]); + } + + public function find(int $id): User + { + $user = $this->repository->findOneBy([ + 'id' => $id, + 'status' => EntityStatusEnum::ENABLED->getValue(), + ]); + + if (null === $user) { + throw new ResourceNotFoundException(); + } + + return $user; + } + + public function save(User $user): void + { + $this->mapaCulturalEntityManager->persist($user); + $this->mapaCulturalEntityManager->flush(); + } + + public function findOneBy(array $params): ?User + { + $params['status'] = EntityStatusEnum::ENABLED->getValue(); + + return $this->repository->findOneBy($params); + } + + public function findBy(array $params): array + { + return $this->repository->findBy($params); + } +} diff --git a/app/src/Request/AgentRequest.php b/app/src/Request/AgentRequest.php index e0ec1ae7ed..43d59846a8 100644 --- a/app/src/Request/AgentRequest.php +++ b/app/src/Request/AgentRequest.php @@ -4,35 +4,29 @@ namespace App\Request; -use Exception; +use App\Exception\FieldRequiredException; use Symfony\Component\HttpFoundation\Request; class AgentRequest { - protected Request $request; - - public function __construct() - { - $this->request = new Request(); + public function __construct( + private readonly Request $request + ) { } public function validatePost(): array { $jsonData = $this->request->getContent(); - $data = json_decode($jsonData, true); + $data = json_decode($jsonData, associative: true); - $requiredFields = ['type', 'name', 'shortDescription', 'terms']; + $requiredFields = ['type', 'name', 'shortDescription']; foreach ($requiredFields as $field) { - if (!isset($data[$field])) { - throw new Exception(ucfirst($field).' is required'); + if (false === isset($data[$field])) { + throw new FieldRequiredException(ucfirst($field)); } } - if (!isset($data['type']) || !is_array($data['terms']) || !is_array($data['terms']['area'])) { - throw new Exception('The "terms" field must be an object with a property "area" which is an array.'); - } - return $data; } diff --git a/app/src/Request/AuthRequest.php b/app/src/Request/AuthRequest.php new file mode 100644 index 0000000000..84298b87ea --- /dev/null +++ b/app/src/Request/AuthRequest.php @@ -0,0 +1,46 @@ +validateAuth(self::GROUP_POST); + } + + private function validateAuth(string $validatorGroup): array + { + $data = json_decode( + json: $this->request->getContent(), + associative: true + ); + + $auth = $this->serializer->denormalize($data, AuthDto::class); + + $violations = $this->validator->validate($auth, groups: [$validatorGroup]); + + if (0 < count($violations)) { + throw new ValidatorException(violations: $violations); + } + + return $data; + } +} diff --git a/app/src/Request/EventRequest.php b/app/src/Request/EventRequest.php index 820e0d7039..e55fabe01e 100644 --- a/app/src/Request/EventRequest.php +++ b/app/src/Request/EventRequest.php @@ -4,57 +4,49 @@ namespace App\Request; -use App\Enum\EntityStatusEnum; -use App\Repository\EventRepository; -use Exception; -use MapasCulturais\Entities\Event; +use App\DTO\EventDto; +use App\Exception\ValidatorException; use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\Serializer\SerializerInterface; +use Symfony\Component\Validator\Validator\ValidatorInterface; class EventRequest { - protected Request $request; - private $repository; + public const GROUP_POST = 'post'; - public function __construct() - { - $this->request = new Request(); - $this->repository = new EventRepository(); + public const GROUP_PATCH = 'patch'; + + public function __construct( + private readonly Request $request, + private readonly SerializerInterface $serializer, + private readonly ValidatorInterface $validator + ) { } public function validatePost(): array { - $jsonData = $this->request->getContent(); - $data = json_decode($jsonData, true); - - $requiredFields = ['name', 'shortDescription', 'classificacaoEtaria', 'terms']; - foreach ($requiredFields as $field) { - if (!isset($data[$field])) { - throw new Exception(ucfirst($field).' is required.'); - } - } - - if (!isset($data['terms']['linguagem']) || !is_array($data['terms']) || !$data['terms']['linguagem']) { - throw new Exception('The "terms" field must be an object with a property "linguagem" which is an array.'); - } + return $this->validateEvent(self::GROUP_POST); + } - return $data; + public function validateUpdate(): array + { + return $this->validateEvent(self::GROUP_PATCH); } - public function validateEventExistent(array $params): Event + public function validateEvent(string $validateGroup): array { - $event = $this->repository->find((int) $params['id']); + $data = json_decode( + json: $this->request->getContent(), + associative: true + ); - if (!$event || EntityStatusEnum::TRASH->getValue() === $event->status) { - throw new Exception('Event not found or already deleted.'); - } + $event = $this->serializer->denormalize($data, EventDto::class); - return $event; - } + $violations = $this->validator->validate($event, groups: [$validateGroup]); - public function validateUpdate(): array - { - $jsonData = $this->request->getContent(); - $data = json_decode($jsonData, true); + if (0 < count($violations)) { + throw new ValidatorException(violations: $violations); + } return $data; } diff --git a/app/src/Request/OpportunityRequest.php b/app/src/Request/OpportunityRequest.php index 193c841dad..532cd07687 100644 --- a/app/src/Request/OpportunityRequest.php +++ b/app/src/Request/OpportunityRequest.php @@ -4,17 +4,15 @@ namespace App\Request; -use App\Enum\EntityStatusEnum; -use Exception; +use App\Exception\FieldRequiredException; +use App\Exception\InvalidRequestException; use Symfony\Component\HttpFoundation\Request; class OpportunityRequest { - protected Request $request; - - public function __construct() - { - $this->request = new Request(); + public function __construct( + private readonly Request $request + ) { } public function validatePost(): array @@ -25,15 +23,15 @@ public function validatePost(): array $requiredFields = ['objectType', 'name', 'terms', 'type']; foreach ($requiredFields as $field) { - if (!isset($data[$field]) || empty($data[$field])) { - throw new Exception(ucfirst($field).' is required.'); + if (false === isset($data[$field]) || true === empty($data[$field])) { + throw new FieldRequiredException(ucfirst($field)); } } $linkFields = ['project', 'event', 'space', 'agent']; foreach ($linkFields as $field) { - if (isset($data[$field]) && !is_array($data[$field])) { - throw new Exception(ucfirst($field).' must be an array if provided.'); + if (true === isset($data[$field]) && false === is_array($data[$field])) { + throw new InvalidRequestException(ucfirst($field).' must be an array if provided.'); } } @@ -47,19 +45,4 @@ public function validateUpdate(): array associative: true ); } - - public function validateDelete(array $params): Opportunity - { - if (!isset($params['id'])) { - throw new Exception('ID is required.'); - } - - $opportunity = $this->repository->find((int) $params['id']); - - if (!$opportunity || EntityStatusEnum::TRASH->getValue() === $opportunity->status) { - throw new Exception('Opportunity not found or already deleted.'); - } - - return $opportunity; - } } diff --git a/app/src/Request/ProjectRequest.php b/app/src/Request/ProjectRequest.php index ae9b7d8ba1..2476917f72 100644 --- a/app/src/Request/ProjectRequest.php +++ b/app/src/Request/ProjectRequest.php @@ -4,16 +4,14 @@ namespace App\Request; -use Exception; +use App\Exception\FieldRequiredException; use Symfony\Component\HttpFoundation\Request; class ProjectRequest { - protected Request $request; - - public function __construct() - { - $this->request = new Request(); + public function __construct( + private readonly Request $request + ) { } public function validatePost(): array @@ -24,8 +22,8 @@ public function validatePost(): array $requiredFields = ['name', 'shortDescription', 'type']; foreach ($requiredFields as $field) { - if (!isset($data[$field])) { - throw new Exception(ucfirst($field).' is required'); + if (false === isset($data[$field])) { + throw new FieldRequiredException(ucfirst($field)); } } diff --git a/app/src/Request/SealRequest.php b/app/src/Request/SealRequest.php index 2c87eb25a3..06ba03def8 100644 --- a/app/src/Request/SealRequest.php +++ b/app/src/Request/SealRequest.php @@ -7,20 +7,16 @@ use App\DTO\SealDto; use App\Exception\ValidatorException; use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\Serializer\Normalizer\ObjectNormalizer; -use Symfony\Component\Serializer\Serializer; -use Symfony\Component\Validator\Validation; +use Symfony\Component\Serializer\SerializerInterface; +use Symfony\Component\Validator\Validator\ValidatorInterface; class SealRequest { - protected Request $request; - - protected Serializer $serializer; - - public function __construct() - { - $this->request = new Request(); - $this->serializer = new Serializer([new ObjectNormalizer()]); + public function __construct( + private readonly Request $request, + private readonly ValidatorInterface $validator, + private readonly SerializerInterface $serializer + ) { } public function validatePost(): array @@ -32,9 +28,7 @@ public function validatePost(): array $seal = $this->serializer->denormalize($data, SealDto::class); - $validation = Validation::createValidatorBuilder()->enableAttributeMapping()->getValidator(); - - $violations = $validation->validate($seal, groups: ['post']); + $violations = $this->validator->validate($seal, groups: ['post']); if (0 < count($violations)) { throw new ValidatorException(violations: $violations); @@ -52,9 +46,7 @@ public function validatePatch(): array $seal = $this->serializer->denormalize($data, SealDto::class); - $validation = Validation::createValidatorBuilder()->enableAttributeMapping()->getValidator(); - - $violations = $validation->validate($seal, groups: ['patch']); + $violations = $this->validator->validate($seal, groups: ['patch']); if (0 < count($violations)) { throw new ValidatorException(violations: $violations); diff --git a/app/src/Request/SpaceRequest.php b/app/src/Request/SpaceRequest.php index c99fdecc8c..9a8ca20ddb 100644 --- a/app/src/Request/SpaceRequest.php +++ b/app/src/Request/SpaceRequest.php @@ -4,16 +4,15 @@ namespace App\Request; -use Exception; +use App\Exception\FieldRequiredException; +use App\Exception\InvalidRequestException; use Symfony\Component\HttpFoundation\Request; class SpaceRequest { - protected Request $request; - - public function __construct() - { - $this->request = new Request(); + public function __construct( + private Request $request + ) { } public function validatePost(): array @@ -24,13 +23,13 @@ public function validatePost(): array $requiredFields = ['name', 'terms', 'type', 'shortDescription']; foreach ($requiredFields as $field) { - if (!isset($data[$field])) { - throw new Exception(ucfirst($field).' is required'); + if (false === isset($data[$field])) { + throw new FieldRequiredException(ucfirst($field)); } } - if (!is_array($data['terms']) || !is_array($data['terms']['area'])) { - throw new Exception('the terms field must be an object with a property "area" which is an array'); + if (false === is_array($data['terms']) || false === is_array($data['terms']['area'])) { + throw new InvalidRequestException('the terms field must be an object with a property "area" which is an array'); } return $data; diff --git a/app/src/Request/TermRequest.php b/app/src/Request/TermRequest.php new file mode 100644 index 0000000000..4b4472459b --- /dev/null +++ b/app/src/Request/TermRequest.php @@ -0,0 +1,53 @@ +validateTerm(self::GROUP_POST); + } + + public function validatePatch(): array + { + return $this->validateTerm(self::GROUP_PATCH); + } + + public function validateTerm(string $validatorGroup): array + { + $data = json_decode( + json: $this->request->getContent(), + associative: true + ); + + $term = $this->serializer->denormalize($data, TermDto::class); + + $violations = $this->validator->validate($term, groups: [$validatorGroup]); + + if (0 < count($violations)) { + throw new ValidatorException(violations: $violations); + } + + return $data; + } +} diff --git a/app/src/Service/AgentService.php b/app/src/Service/AgentService.php index a0e34dd5fd..154ff685c5 100644 --- a/app/src/Service/AgentService.php +++ b/app/src/Service/AgentService.php @@ -4,24 +4,21 @@ namespace App\Service; -use App\Enum\EntityStatusEnum; -use App\Exception\ResourceNotFoundException; -use App\Repository\AgentRepository; +use App\Repository\Interface\AgentRepositoryInterface; +use App\Repository\Interface\UserRepositoryInterface; +use App\Service\Interface\AgentServiceInterface; use MapasCulturais\Entities\Agent; -use Symfony\Component\Serializer\Normalizer\ObjectNormalizer; -use Symfony\Component\Serializer\Serializer; use Symfony\Component\Serializer\SerializerInterface; -class AgentService +class AgentService implements AgentServiceInterface { - protected AgentRepository $repository; - private SerializerInterface $serializer; public const FILE_TYPES = '/src/conf/agent-types.php'; - public function __construct() - { - $this->repository = new AgentRepository(); - $this->serializer = new Serializer([new ObjectNormalizer()]); + public function __construct( + private readonly AgentRepositoryInterface $repository, + private readonly UserRepositoryInterface $userRepository, + private readonly SerializerInterface $serializer + ) { } public function getTypes(): array @@ -35,17 +32,10 @@ public function getTypes(): array ); } - /** - * @throws ResourceNotFoundException - */ public function update(int $id, object $data): Agent { $agentFromDB = $this->repository->find($id); - if (null === $agentFromDB || EntityStatusEnum::TRASH->getValue() === $agentFromDB->status) { - throw new ResourceNotFoundException('Agent not found'); - } - $agentUpdated = $this->serializer->denormalize( data: $data, type: Agent::class, @@ -58,31 +48,23 @@ public function update(int $id, object $data): Agent return $agentUpdated; } - public function create($data): Agent + public function create(mixed $data): Agent { - $agent = new Agent(); + $user = $this->userRepository->find(1); + + $agent = new Agent($user); $agent->setName($data->name); $agent->setShortDescription($data->shortDescription); $agent->setType($data->type); - $agent->terms['area'] = $data->terms['area']; - $agent->saveTerms(); $this->repository->save($agent); return $agent; } - /** - * @throws ResourceNotFoundException - */ - public function discard(int $id): void + public function removeById(int $id): void { $agent = $this->repository->find($id); - - if (null === $agent || EntityStatusEnum::TRASH->getValue() === $agent->status) { - throw new ResourceNotFoundException('Agent not found'); - } - - $this->repository->softDelete($agent); + $this->repository->remove($agent); } } diff --git a/app/src/Service/EventService.php b/app/src/Service/EventService.php index 4c8500a9ee..7258729b96 100644 --- a/app/src/Service/EventService.php +++ b/app/src/Service/EventService.php @@ -4,28 +4,19 @@ namespace App\Service; -use App\Enum\EntityStatusEnum; -use App\Repository\EventRepository; -use App\Request\EventRequest; +use App\Repository\Interface\EventRepositoryInterface; +use App\Service\Interface\EventServiceInterface; use MapasCulturais\Entities\Event; -use Symfony\Component\Routing\Exception\ResourceNotFoundException; -use Symfony\Component\Serializer\Normalizer\ObjectNormalizer; -use Symfony\Component\Serializer\Serializer; use Symfony\Component\Serializer\SerializerInterface; -class EventService +class EventService implements EventServiceInterface { - protected EventRepository $repository; - protected EventRequest $eventRequest; - public const FILE_TYPES = '/src/conf/event-types.php'; - private SerializerInterface $serializer; - public function __construct() - { - $this->repository = new EventRepository(); - $this->eventRequest = new EventRequest(); - $this->serializer = new Serializer([new ObjectNormalizer()]); + public function __construct( + private readonly EventRepositoryInterface $repository, + private readonly SerializerInterface $serializer + ) { } public function getTypes(): array @@ -35,7 +26,7 @@ public function getTypes(): array return array_map(fn ($key, $item) => ['id' => $key, 'name' => $item['name']], array_keys($typesFromConf), $typesFromConf); } - public function create($data): Event + public function create(mixed $data): Event { $event = new Event(); @@ -53,10 +44,6 @@ public function update(int $id, object $data): Event { $eventFromDB = $this->repository->find($id); - if (null === $eventFromDB || EntityStatusEnum::TRASH->getValue() === $eventFromDB->status) { - throw new ResourceNotFoundException('Event not found or already deleted.'); - } - $eventUpdated = $this->serializer->denormalize( data: $data, type: Event::class, @@ -68,4 +55,10 @@ public function update(int $id, object $data): Event return $eventUpdated; } + + public function removeById(int $id): void + { + $event = $this->repository->find($id); + $this->repository->remove($event); + } } diff --git a/app/src/Service/Interface/AgentServiceInterface.php b/app/src/Service/Interface/AgentServiceInterface.php new file mode 100644 index 0000000000..7f618621eb --- /dev/null +++ b/app/src/Service/Interface/AgentServiceInterface.php @@ -0,0 +1,18 @@ +repository = new OpportunityRepository(); - $this->serializer = new Serializer([new ObjectNormalizer()]); + public function __construct( + private readonly OpportunityRepositoryInterface $repository, + private readonly SerializerInterface $serializer + ) { } public function getTypes(): array { - $typesFromConf = (require dirname(__DIR__, 3).'/src/conf/opportunity-types.php')['items'] ?? []; + $typesFromConf = (require dirname(__DIR__, 3).self::FILE_TYPES)['items'] ?? []; return array_map( fn ($key, $item) => ['id' => $key, 'name' => $item['name']], @@ -40,11 +33,6 @@ public function getTypes(): array public function update(int $id, object $data): Opportunity { $opportunityFromDB = $this->repository->find($id); - - if (null === $opportunityFromDB || EntityStatusEnum::TRASH->getValue() === $opportunityFromDB->status) { - throw new ResourceNotFoundException('Opportunity not found'); - } - $opportunityUpdated = $this->serializer->denormalize( data: $data, type: Opportunity::class, @@ -57,7 +45,7 @@ public function update(int $id, object $data): Opportunity return $opportunityUpdated; } - public function create($data): Opportunity + public function create(mixed $data): Opportunity { $opportunity = new Opportunity(); @@ -65,19 +53,19 @@ public function create($data): Opportunity $opportunity->setName($data['name']); $opportunity->terms['area'] = $data['terms']['area']; - if (isset($data['project'])) { + if (true === isset($data['project'])) { $opportunity->setObjectType("MapasCulturais\Entities\Project"); $opportunity->setProject($data['project']); } - if (isset($data['event'])) { + if (true === isset($data['event'])) { $opportunity->setObjectType("MapasCulturais\Entities\Event"); $opportunity->setEvent($data['event']); } - if (isset($data['space'])) { + if (true === isset($data['space'])) { $opportunity->setObjectType("MapasCulturais\Entities\Space"); $opportunity->setSpace($data['space']); } - if (isset($data['agent'])) { + if (true === isset($data['agent'])) { $opportunity->setObjectType("MapasCulturais\Entities\Agent"); $opportunity->setAgent($data['agent']); } @@ -86,4 +74,10 @@ public function create($data): Opportunity return $opportunity; } + + public function removeById(int $id): void + { + $opportunity = $this->repository->find($id); + $this->repository->remove($opportunity); + } } diff --git a/app/src/Service/ProjectService.php b/app/src/Service/ProjectService.php index 1c38077f04..8361218f73 100644 --- a/app/src/Service/ProjectService.php +++ b/app/src/Service/ProjectService.php @@ -4,27 +4,32 @@ namespace App\Service; -use App\Enum\EntityStatusEnum; -use App\Repository\ProjectRepository; +use App\Exception\FieldRequiredException; +use App\Repository\Interface\ProjectRepositoryInterface; +use App\Service\Interface\ProjectServiceInterface; use MapasCulturais\Entities\Project; -use Symfony\Component\Routing\Exception\ResourceNotFoundException; -use Symfony\Component\Serializer\Normalizer\ObjectNormalizer; -use Symfony\Component\Serializer\Serializer; use Symfony\Component\Serializer\SerializerInterface; -class ProjectService +class ProjectService implements ProjectServiceInterface { - protected ProjectRepository $projectRepository; - private SerializerInterface $serializer; - - public function __construct() - { - $this->projectRepository = new ProjectRepository(); - $this->serializer = new Serializer([new ObjectNormalizer()]); + public function __construct( + private readonly ProjectRepositoryInterface $projectRepository, + private readonly SerializerInterface $serializer + ) { } - public function create($data): Project + public function create(mixed $data): Project { + if (true === empty($data->name)) { + throw new FieldRequiredException('The name field is required.'); + } + if (true === empty($data->shortDescription)) { + throw new FieldRequiredException('The shortDescription field is required.'); + } + if (true === empty($data->type)) { + throw new FieldRequiredException('The type field is required.'); + } + $project = new Project(); $project->setName($data->name); $project->setShortDescription($data->shortDescription); @@ -39,8 +44,8 @@ public function update(int $id, object $data): Project { $projectFromDB = $this->projectRepository->find($id); - if (null === $projectFromDB || EntityStatusEnum::TRASH->getValue() === $projectFromDB->status) { - throw new ResourceNotFoundException('Project not found or already deleted.'); + if (true === empty($data->name)) { + throw new FieldRequiredException('name'); } $projectUpdated = $this->serializer->denormalize( @@ -48,6 +53,7 @@ public function update(int $id, object $data): Project type: Project::class, context: ['object_to_populate' => $projectFromDB] ); + $projectUpdated->saveTerms(); $projectUpdated->saveMetadata(); @@ -56,17 +62,9 @@ public function update(int $id, object $data): Project return $projectUpdated; } - /** - * @throws ResourceNotFoundException - */ - public function discard(int $id): void + public function removeById(int $id): void { $project = $this->projectRepository->find($id); - - if (null === $project || EntityStatusEnum::TRASH->getValue() === $project->status) { - throw new ResourceNotFoundException('Project not found or already deleted.'); - } - - $this->$project->softDelete($project); + $this->projectRepository->remove($project); } } diff --git a/app/src/Service/SealService.php b/app/src/Service/SealService.php index 2cf1ff2583..edba981a8f 100644 --- a/app/src/Service/SealService.php +++ b/app/src/Service/SealService.php @@ -4,32 +4,22 @@ namespace App\Service; -use App\Enum\EntityStatusEnum; -use App\Exception\ResourceNotFoundException; -use App\Repository\AgentRepository; -use App\Repository\ProjectRepository; -use App\Repository\SealRepository; +use App\Repository\Interface\AgentRepositoryInterface; +use App\Repository\Interface\SealRepositoryInterface; +use App\Service\Interface\SealServiceInterface; use MapasCulturais\Entities\Seal; -use Symfony\Component\Serializer\Normalizer\ObjectNormalizer; -use Symfony\Component\Serializer\Serializer; use Symfony\Component\Serializer\SerializerInterface; -class SealService extends AbstractService +class SealService extends AbstractService implements SealServiceInterface { - private SealRepository $sealRepository; - private AgentRepository $agentRepository; - protected ProjectRepository $projectRepository; - private SerializerInterface $serializer; - - public function __construct() - { - $this->projectRepository = new ProjectRepository(); - $this->serializer = new Serializer([new ObjectNormalizer()]); - $this->sealRepository = new SealRepository(); - $this->agentRepository = new AgentRepository(); + public function __construct( + private readonly AgentRepositoryInterface $agentRepository, + private readonly SealRepositoryInterface $sealRepository, + private readonly SerializerInterface $serializer + ) { } - public function create(array $data): mixed + public function create(mixed $data): Seal { $seal = $this->serializer->denormalize($data, Seal::class); $this->setProperty($seal, 'owner', $this->agentRepository->find(1)); @@ -38,33 +28,16 @@ public function create(array $data): mixed return $seal; } - /** - * @throws ResourceNotFoundException - */ - public function delete(int $id): true + public function removeById(int $id): void { $seal = $this->sealRepository->find($id); - - if (null === $seal || EntityStatusEnum::TRASH->getValue() === $seal->status) { - throw new ResourceNotFoundException('Seal not found'); - } - - $this->sealRepository->softDelete($seal); - - return true; + $this->sealRepository->remove($seal); } - /** - * @throws ResourceNotFoundException - */ public function update(int $id, object $data): Seal { $sealFromDB = $this->sealRepository->find($id); - if (null === $sealFromDB || EntityStatusEnum::TRASH->getValue() === $sealFromDB->status) { - throw new ResourceNotFoundException('Seal not found'); - } - $sealUpdated = $this->serializer->denormalize( data: $data, type: Seal::class, diff --git a/app/src/Service/SpaceService.php b/app/src/Service/SpaceService.php index 216d107107..1ccfc80f4b 100644 --- a/app/src/Service/SpaceService.php +++ b/app/src/Service/SpaceService.php @@ -4,25 +4,19 @@ namespace App\Service; -use App\Enum\EntityStatusEnum; -use App\Exception\ResourceNotFoundException; -use App\Repository\SpaceRepository; +use App\Repository\Interface\SpaceRepositoryInterface; +use App\Service\Interface\SpaceServiceInterface; use MapasCulturais\Entities\Space; -use Symfony\Component\Serializer\Normalizer\ObjectNormalizer; -use Symfony\Component\Serializer\Serializer; use Symfony\Component\Serializer\SerializerInterface; -class SpaceService +class SpaceService implements SpaceServiceInterface { - protected SpaceRepository $repository; - private SerializerInterface $serializer; - public const FILE_TYPES = '/src/conf/space-types.php'; - public function __construct() - { - $this->repository = new SpaceRepository(); - $this->serializer = new Serializer([new ObjectNormalizer()]); + public function __construct( + private readonly SerializerInterface $serializer, + private readonly SpaceRepositoryInterface $repository + ) { } public function getTypes(): array @@ -36,7 +30,7 @@ public function getTypes(): array ); } - public function create($data): Space + public function create(mixed $data): Space { $space = new Space(); @@ -51,21 +45,19 @@ public function create($data): Space return $space; } - /** - * @throws ResourceNotFoundException - */ - public function update($id, $data): Space + public function update(int $id, object $data): Space { $spaceFromDB = $this->repository->find($id); - - if (null === $spaceFromDB || EntityStatusEnum::TRASH->getValue() === $spaceFromDB->status) { - throw new ResourceNotFoundException('Space not found'); - } - - $spaceUpdated = $this->serializer->denormalize($data, Space::class, null, ['object_to_populate' => $spaceFromDB]); + $spaceUpdated = $this->serializer->denormalize($data, Space::class, context: ['object_to_populate' => $spaceFromDB]); $this->repository->save($spaceUpdated); return $spaceUpdated; } + + public function removeById(int $id): void + { + $space = $this->repository->find($id); + $this->repository->remove($space); + } } diff --git a/app/src/Service/TermService.php b/app/src/Service/TermService.php new file mode 100644 index 0000000000..d836d4dcca --- /dev/null +++ b/app/src/Service/TermService.php @@ -0,0 +1,48 @@ +serializer->denormalize($data, Term::class); + $this->termRepository->save($term); + + return $term; + } + + public function update(int $id, array $termData): Term + { + $termFromDB = $this->termRepository->find($id); + + $termUpdated = $this->serializer->denormalize( + data: $termData, + type: Term::class, + context: ['object_to_populate' => $termFromDB] + ); + + $this->termRepository->save($termUpdated); + + return $termUpdated; + } + + public function removeById(int $id): void + { + $term = $this->termRepository->find($id); + $this->termRepository->remove($term); + } +} diff --git a/app/src/Service/UserService.php b/app/src/Service/UserService.php new file mode 100644 index 0000000000..66faca5be5 --- /dev/null +++ b/app/src/Service/UserService.php @@ -0,0 +1,39 @@ +repository->find($id); + } + + public function findOneBy(array $params): User + { + $user = $this->repository->findOneBy($params); + + if (null === $user) { + throw new ResourceNotFoundException(); + } + + return $user; + } + + public function save(User $user): void + { + $this->repository->save($user); + } +} diff --git a/app/src/Validator/Constraints/UniqueInEntity.php b/app/src/Validator/Constraints/UniqueInEntity.php new file mode 100644 index 0000000000..74ff494ab2 --- /dev/null +++ b/app/src/Validator/Constraints/UniqueInEntity.php @@ -0,0 +1,27 @@ +entity = $app->em; + } + + public function validate(mixed $value, Constraint $constraint): void + { + if (false === $constraint instanceof UniqueInEntity) { + throw new UnexpectedTypeException($constraint, UniqueInEntity::class); + } + + if (null === $value || '' === $value) { + return; + } + + $result = $this->entity->getRepository($constraint->entity)->findBy([$constraint->field => $value]); + + if ([] === $result) { + return; + } + + $this->context->buildViolation($constraint->message)->addViolation(); + } +} diff --git a/app/tests/functional/AgentApiControllerTest.php b/app/tests/Functional/AgentApiControllerTest.php similarity index 91% rename from app/tests/functional/AgentApiControllerTest.php rename to app/tests/Functional/AgentApiControllerTest.php index 864df8684d..6405e3bbec 100644 --- a/app/tests/functional/AgentApiControllerTest.php +++ b/app/tests/Functional/AgentApiControllerTest.php @@ -2,9 +2,10 @@ declare(strict_types=1); -namespace App\Tests; +namespace App\Tests\Functional; use App\DataFixtures\AgentFixtures; +use App\Tests\AbstractTestCase; use App\Tests\fixtures\AgentTestFixtures; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; @@ -42,7 +43,6 @@ public function testGetAgentTypesShouldRetrieveAList(): void public function testGetAgentOpportunitiesShouldRetrieveAList(): void { - $this->markTestSkipped(); $response = $this->client->request(Request::METHOD_GET, self::BASE_URL.'/1/opportunities'); $content = json_decode($response->getContent()); @@ -52,7 +52,6 @@ public function testGetAgentOpportunitiesShouldRetrieveAList(): void public function testCreateAgentShouldCreateAnAgent(): void { - $this->markTestSkipped(); $agentTestFixtures = AgentTestFixtures::partial(); $response = $this->client->request(Request::METHOD_POST, self::BASE_URL, [ @@ -61,18 +60,14 @@ public function testCreateAgentShouldCreateAnAgent(): void $this->assertEquals(Response::HTTP_CREATED, $response->getStatusCode()); - $content = json_decode($response->getContent(), true); + $content = json_decode($response->getContent()); - foreach ($agentTestFixtures->toArray() as $key => $value) { - $this->assertEquals($value, $content[$key]); - } + $this->assertEquals('Agent Test', $content->name); } public function testDeleteAgentShouldReturnSuccess(): void { - $this->markTestSkipped(); $response = $this->client->request(Request::METHOD_DELETE, self::BASE_URL.'/2'); - $this->assertEquals(Response::HTTP_NO_CONTENT, $response->getStatusCode()); $response = $this->client->request(Request::METHOD_GET, self::BASE_URL.'/2'); @@ -108,7 +103,7 @@ public function testUpdateNotFoundedResource(): void ]); $error = [ - 'error' => 'Agent not found', + 'error' => 'The resource was not found.', ]; $content = json_decode($response->getContent(false), true); diff --git a/app/tests/Functional/AuthApiControllerTest.php b/app/tests/Functional/AuthApiControllerTest.php new file mode 100644 index 0000000000..112d07e110 --- /dev/null +++ b/app/tests/Functional/AuthApiControllerTest.php @@ -0,0 +1,95 @@ +client->request(Request::METHOD_POST, self::BASE_URL, [ + 'json' => [ + 'email' => 'chiquim@email.com', + 'password' => '12345678', + ], + ]); + + $this->assertEquals(Response::HTTP_NOT_FOUND, $response->getStatusCode()); + } + + public function testAuthenticationWithInvalidPasswordShouldReturnInvalidCredentials(): void + { + $response = $this->client->request(Request::METHOD_POST, self::BASE_URL, [ + 'json' => [ + 'email' => 'Admin@local', + 'password' => '12345678', + ], + ]); + + $responseData = $response->toArray(throw: false); + + $this->assertEquals(Response::HTTP_BAD_REQUEST, $response->getStatusCode()); + $this->assertEquals('Invalid Credentials', $responseData['error']); + } + + /** + * @dataProvider userDataProvider + */ + public function testUserValidations(array $userData, array $expectedMessages): void + { + $this->validateUser($userData, $expectedMessages); + } + + private function validateUser(array $userData, array $expectedMessages): void + { + $response = $this->client->request(Request::METHOD_POST, self::BASE_URL, [ + 'json' => $userData, + ]); + + $statusCode = $response->getStatusCode(); + $responseData = $response->toArray(false); + + $this->assertEquals(Response::HTTP_BAD_REQUEST, $statusCode); + $this->assertEquals('The provided data violates one or more constraints.', $responseData['error']); + + $actualMessages = array_map( + fn ($fieldError) => $fieldError['message'], + $responseData['fields'] + ); + + $this->assertEquals($expectedMessages, $actualMessages); + } + + public static function userDataProvider(): array + { + return [ + 'blank fields' => [ + 'userData' => [ + 'email' => '', + 'password' => '', + ], + 'expectedMessages' => [ + 'This value should not be blank.', + 'This value should not be blank.', + ], + ], + 'invalid type fields' => [ + 'userData' => [ + 'email' => 123, + 'string' => 123, + ], + 'expectedMessages' => [ + 'This value should be of type string.', + 'This value should not be blank.', + ], + ], + ]; + } +} diff --git a/app/tests/Functional/EventApiControllerTest.php b/app/tests/Functional/EventApiControllerTest.php new file mode 100644 index 0000000000..8800fb7aea --- /dev/null +++ b/app/tests/Functional/EventApiControllerTest.php @@ -0,0 +1,172 @@ +client->request(Request::METHOD_GET, self::BASE_URL); + $content = json_decode($response->getContent(), true); + + $this->assertEquals(Response::HTTP_OK, $response->getStatusCode()); + $this->assertIsArray($content); + + $this->assertArrayHasKey('id', $content[0]); + $this->assertArrayHasKey('name', $content[0]); + + $this->assertEquals(1, $content[0]['id']); + $this->assertEquals('Evento de Cultura', $content[0]['name']); + } + + public function testGetOneEventShouldRetrieveAObject(): void + { + $response = $this->client->request(Request::METHOD_GET, self::BASE_URL.'/1'); + $content = json_decode($response->getContent()); + + $this->assertEquals(Response::HTTP_OK, $response->getStatusCode()); + $this->assertIsObject($content); + + $this->assertObjectHasProperty('@entityType', $content); + $this->assertEquals('event', $content->{'@entityType'}); + } + + public function testGetOneEventShouldReturnNotFound(): void + { + $nonExistentId = 99999999; + $response = $this->client->request(Request::METHOD_GET, self::BASE_URL.'/'.$nonExistentId); + + $this->assertEquals(Response::HTTP_NOT_FOUND, $response->getStatusCode()); + } + + public function testCreateEventShouldCreateANewEvent(): void + { + $eventTestFixtures = EventTestFixtures::partial(); + + $response = $this->client->request(Request::METHOD_POST, self::BASE_URL, [ + 'body' => $eventTestFixtures->json(), + ]); + + $this->assertEquals(Response::HTTP_CREATED, $response->getStatusCode()); + } + + public function testUpdateEventShouldUpdateAnEvent(): void + { + $eventTestFixtures = EventTestFixtures::partial(); + + $response = $this->client->request(Request::METHOD_PATCH, self::BASE_URL.'/1', [ + 'body' => $eventTestFixtures->json(), + ]); + + $this->assertEquals(Response::HTTP_OK, $response->getStatusCode()); + } + + public function testDeleteEventShouldReturnNoContent(): void + { + $response = $this->client->request(Request::METHOD_DELETE, self::BASE_URL.'/1'); + + $this->assertEquals(Response::HTTP_NO_CONTENT, $response->getStatusCode()); + } + + public function testDeleteEventShouldReturnNotFound(): void + { + $nonExistentId = 99999999; + $response = $this->client->request(Request::METHOD_DELETE, self::BASE_URL.'/'.$nonExistentId); + + $this->assertEquals(Response::HTTP_NOT_FOUND, $response->getStatusCode()); + } + + /** + * @dataProvider eventDataProvider + */ + public function testEventValidations(array $eventData, array $expectedMessages): void + { + $this->validateEvent($eventData, $expectedMessages); + } + + private function validateEvent(array $eventData, array $expectedMessages): void + { + $response = $this->client->request(Request::METHOD_POST, self::BASE_URL, [ + 'json' => $eventData, + ]); + + $statusCode = $response->getStatusCode(); + $responseData = $response->toArray(false); + + $this->assertEquals(Response::HTTP_BAD_REQUEST, $statusCode); + $this->assertEquals('The provided data violates one or more constraints.', $responseData['error']); + + $actualMessages = array_map(function ($fieldError) { + return $fieldError['message']; + }, $responseData['fields']); + + $this->assertEquals($expectedMessages, $actualMessages); + } + + public static function eventDataProvider(): array + { + return [ + 'blank fields' => [ + 'eventData' => [ + 'name' => '', + 'shortDescription' => '', + 'classificacaoEtaria' => '', + 'terms' => [ + 'linguagem' => [], + ], + ], + 'expectedMessages' => [ + 'This value should not be blank.', + 'This value is too short. It should have 2 characters or more.', + 'This value should not be blank.', + 'This value is too short. It should have 2 characters or more.', + 'This value should not be blank.', + 'This value is too short. It should have 2 characters or more.', + 'This value should not be blank.', + 'This collection should contain 1 element or more.', + ], + ], + 'invalid type fields' => [ + 'eventData' => [ + 'name' => 123, + 'shortDescription' => 123, + 'classificacaoEtaria' => 123, + 'terms' => [ + 'linguagem' => [123], + 'tag' => [123], + ], + ], + 'expectedMessages' => [ + 'This value should be of type string.', + 'This value should be of type string.', + 'This value should be of type string.', + 'This value should be of type string.', + 'This value should be of type string.', + ], + ], + 'missing required field linguagem' => [ + 'eventData' => [ + 'name' => 'Evento Teste', + 'shortDescription' => 'Descrição curta do evento', + 'classificacaoEtaria' => 'livre', + 'terms' => [ + 'linguagem' => [], + ], + ], + 'expectedMessages' => [ + 'This value should not be blank.', + 'This collection should contain 1 element or more.', + ], + ], + ]; + } +} diff --git a/app/tests/functional/OpportunityApiControllerTest.php b/app/tests/Functional/OpportunityApiControllerTest.php similarity index 93% rename from app/tests/functional/OpportunityApiControllerTest.php rename to app/tests/Functional/OpportunityApiControllerTest.php index 42a3be0da6..37c731bfcc 100644 --- a/app/tests/functional/OpportunityApiControllerTest.php +++ b/app/tests/Functional/OpportunityApiControllerTest.php @@ -2,8 +2,9 @@ declare(strict_types=1); -namespace App\Tests; +namespace App\Tests\Functional; +use App\Tests\AbstractTestCase; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; diff --git a/app/tests/functional/ProjectApiControllerTest.php b/app/tests/Functional/ProjectApiControllerTest.php similarity index 88% rename from app/tests/functional/ProjectApiControllerTest.php rename to app/tests/Functional/ProjectApiControllerTest.php index d62be07c48..80d89300f1 100644 --- a/app/tests/functional/ProjectApiControllerTest.php +++ b/app/tests/Functional/ProjectApiControllerTest.php @@ -2,9 +2,10 @@ declare(strict_types=1); -namespace App\Tests; +namespace App\Tests\Functional; use App\DataFixtures\ProjectFixtures; +use App\Tests\AbstractTestCase; use App\Tests\fixtures\ProjectTestFixtures; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; @@ -43,14 +44,11 @@ public function testCreateProjectShouldCreateAProject(): void $content = json_decode($response->getContent(), true); - foreach ($projectTestFixtures->toArray() as $key => $value) { - $this->assertEquals($value, $content[$key]); - } + $this->assertEquals('Project Test', $content['name']); } - public function testDeleteProjectShouldReturnSuccess(): void + public function testDeleteProjectShouldReturnNoContent(): void { - $this->markTestSkipped(); $response = $this->client->request(Request::METHOD_DELETE, self::BASE_URL.'/1'); $this->assertEquals(Response::HTTP_NO_CONTENT, $response->getStatusCode()); @@ -86,11 +84,11 @@ public function testUpdateNotFoundedProjectResource(): void ]); $error = [ - 'error' => 'Project not found or already deleted.', + 'error' => 'The resource was not found.', ]; $content = json_decode($response->getContent(false), true); - $this->assertEquals(Response::HTTP_BAD_REQUEST, $response->getStatusCode()); + $this->assertEquals(Response::HTTP_NOT_FOUND, $response->getStatusCode()); $this->assertIsArray($content); $this->assertEquals($error, $content); } diff --git a/app/tests/functional/SealApiControllerTest.php b/app/tests/Functional/SealApiControllerTest.php similarity index 85% rename from app/tests/functional/SealApiControllerTest.php rename to app/tests/Functional/SealApiControllerTest.php index 96bbd1c12d..99600d866f 100644 --- a/app/tests/functional/SealApiControllerTest.php +++ b/app/tests/Functional/SealApiControllerTest.php @@ -2,9 +2,10 @@ declare(strict_types=1); -namespace App\Tests; +namespace App\Tests\Functional; use App\DataFixtures\SealFixtures; +use App\Tests\AbstractTestCase; use App\Tests\fixtures\SealTestFixtures; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; @@ -24,7 +25,9 @@ public function testGetSealsShouldRetrieveAList(): void public function testGetOneSealShouldRetrieveAObject(): void { - $response = $this->client->request(Request::METHOD_GET, self::BASE_URL.'/1'); + $url = sprintf('%s/%s', self::BASE_URL, SealFixtures::SEAL_ID_4); + + $response = $this->client->request(Request::METHOD_GET, $url); $content = json_decode($response->getContent()); $this->assertEquals(Response::HTTP_OK, $response->getStatusCode()); @@ -33,7 +36,6 @@ public function testGetOneSealShouldRetrieveAObject(): void public function testCreateSealShouldReturnCreatedSeal(): void { - $this->markTestSkipped(); $sealTestFixtures = SealTestFixtures::partial(); $response = $this->client->request(Request::METHOD_POST, self::BASE_URL, [ @@ -50,21 +52,20 @@ public function testCreateSealShouldReturnCreatedSeal(): void public function testDeleteSealShouldReturnSuccess(): void { - $this->markTestSkipped(); - $sealId = SealFixtures::SEAL_ID_6; + $url = sprintf('%s/%s', self::BASE_URL, SealFixtures::SEAL_ID_3); - $response = $this->client->request(Request::METHOD_DELETE, sprintf(self::BASE_URL.'/%s', $sealId)); + $response = $this->client->request(Request::METHOD_DELETE, $url); $this->assertEquals(Response::HTTP_NO_CONTENT, $response->getStatusCode()); - $response = $this->client->request(Request::METHOD_GET, sprintf(self::BASE_URL.'/%s', $sealId)); - $this->assertEquals(Response::HTTP_OK, $response->getStatusCode()); + $response = $this->client->request(Request::METHOD_GET, $url); + $this->assertEquals(Response::HTTP_NOT_FOUND, $response->getStatusCode()); } public function testUpdate(): void { - $this->markTestSkipped(); $sealTestFixtures = SealTestFixtures::partial(); - $url = sprintf(self::BASE_URL.'/%s', SealFixtures::SEAL_ID_3); + + $url = sprintf('%s/%s', self::BASE_URL, SealFixtures::SEAL_ID_4); $response = $this->client->request(Request::METHOD_PATCH, $url, [ 'body' => $sealTestFixtures->json(), @@ -81,14 +82,15 @@ public function testUpdate(): void public function testUpdateNotFoundedResource(): void { $sealTestFixtures = SealTestFixtures::partial(); - $url = sprintf(self::BASE_URL.'/%s', 80); + + $url = sprintf('%s/%s', self::BASE_URL, 80); $response = $this->client->request(Request::METHOD_PATCH, $url, [ 'body' => $sealTestFixtures->json(), ]); $error = [ - 'error' => 'Seal not found', + 'error' => 'The resource was not found.', ]; $content = json_decode($response->getContent(false), true); diff --git a/app/tests/functional/SpaceApiControllerTest.php b/app/tests/Functional/SpaceApiControllerTest.php similarity index 90% rename from app/tests/functional/SpaceApiControllerTest.php rename to app/tests/Functional/SpaceApiControllerTest.php index cf221d9f2f..a814f2729f 100644 --- a/app/tests/functional/SpaceApiControllerTest.php +++ b/app/tests/Functional/SpaceApiControllerTest.php @@ -2,9 +2,10 @@ declare(strict_types=1); -namespace App\Tests; +namespace App\Tests\Functional; use App\DataFixtures\SpaceFixtures; +use App\Tests\AbstractTestCase; use App\Tests\fixtures\SpaceTestFixtures; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; @@ -33,7 +34,6 @@ public function testGetOneSpaceShouldRetrieveAObject(): void public function testCreateSpaceShouldReturnCreatedSpace(): void { - $this->markTestSkipped(); $spaceTestFixtures = SpaceTestFixtures::partial(); $response = $this->client->request(Request::METHOD_POST, self::BASE_URL, [ @@ -41,16 +41,22 @@ public function testCreateSpaceShouldReturnCreatedSpace(): void ]); $content = json_decode($response->getContent(), true); + $this->assertEquals(Response::HTTP_CREATED, $response->getStatusCode()); $this->assertIsArray($content); + foreach ($spaceTestFixtures->toArray() as $key => $value) { + if ('type' === $key) { + $this->assertEquals($value, $content[$key]['id']); + continue; + } + $this->assertEquals($value, $content[$key]); } } public function testDeleteSpaceShouldReturnSuccess(): void { - $this->markTestSkipped(); $response = $this->client->request(Request::METHOD_DELETE, self::BASE_URL.'/1'); $this->assertEquals(Response::HTTP_NO_CONTENT, $response->getStatusCode()); @@ -59,7 +65,7 @@ public function testDeleteSpaceShouldReturnSuccess(): void $this->assertEquals(Response::HTTP_NOT_FOUND, $response->getStatusCode()); } - public function testUpdate(): void + public function testUpdateSpaceShouldReturnUpdatedSpace(): void { $spaceTestFixtures = SpaceTestFixtures::partial(); $url = sprintf(self::BASE_URL.'/%s', SpaceFixtures::SPACE_ID_3); @@ -71,6 +77,7 @@ public function testUpdate(): void $content = json_decode($response->getContent(), true); $this->assertEquals(Response::HTTP_CREATED, $response->getStatusCode()); $this->assertIsArray($content); + foreach ($spaceTestFixtures->toArray() as $key => $value) { $this->assertEquals($value, $content[$key]); } @@ -86,7 +93,7 @@ public function testUpdateNotFoundedResource(): void ]); $error = [ - 'error' => 'Space not found', + 'error' => 'The resource was not found.', ]; $content = json_decode($response->getContent(false), true); diff --git a/app/tests/Functional/TermApiControllerTest.php b/app/tests/Functional/TermApiControllerTest.php new file mode 100644 index 0000000000..c973cdf6e0 --- /dev/null +++ b/app/tests/Functional/TermApiControllerTest.php @@ -0,0 +1,178 @@ +client->request(Request::METHOD_GET, self::BASE_URL); + $content = json_decode($response->getContent(), true); + + $this->assertEquals(Response::HTTP_OK, $response->getStatusCode()); + $this->assertIsArray($content); + + $this->assertArrayHasKey('id', $content[0]); + $this->assertArrayHasKey('taxonomy', $content[0]); + + $this->assertEquals(1, $content[0]['id']); + $this->assertEquals('area', $content[0]['taxonomy']); + } + + public function testGetOneTermShouldRetrieveAObject(): void + { + $response = $this->client->request(Request::METHOD_GET, self::BASE_URL.'/1'); + $content = json_decode($response->getContent()); + + $this->assertEquals(Response::HTTP_OK, $response->getStatusCode()); + $this->assertIsObject($content); + + $this->assertObjectHasProperty('@entityType', $content); + $this->assertEquals('term', $content->{'@entityType'}); + } + + public function testGetOneTermShouldReturnNotFound(): void + { + $nonExistentId = 99999999; + $response = $this->client->request(Request::METHOD_GET, self::BASE_URL.'/'.$nonExistentId); + + $this->assertEquals(Response::HTTP_NOT_FOUND, $response->getStatusCode()); + } + + public function testCreateTermShouldCreateANewTerm(): void + { + $termTestFixtures = TermTestFixtures::partial(); + + $response = $this->client->request(Request::METHOD_POST, self::BASE_URL, [ + 'body' => $termTestFixtures->json(), + ]); + + $this->assertEquals(Response::HTTP_CREATED, $response->getStatusCode()); + + $content = json_decode($response->getContent(), true); + + foreach ($termTestFixtures->toArray() as $key => $value) { + $this->assertEquals($value, $content[$key]); + } + } + + public function testDeleteTermShouldReturnNoContent(): void + { + $response = $this->client->request(Request::METHOD_DELETE, self::BASE_URL.'/1'); + + $this->assertEquals(Response::HTTP_NO_CONTENT, $response->getStatusCode()); + } + + public function testDeletedTermShouldReturnNotFound(): void + { + $this->client->request(Request::METHOD_DELETE, self::BASE_URL.'/202'); + + $response = $this->client->request(Request::METHOD_DELETE, self::BASE_URL.'/202'); + + $this->assertEquals(Response::HTTP_NOT_FOUND, $response->getStatusCode()); + } + + public function testTermUpdateShouldReturnUpdatedTerm(): void + { + $response = $this->client->request(Request::METHOD_PATCH, self::BASE_URL.'/2', [ + 'body' => json_encode([ + 'term' => 'Update term', + ]), + ]); + + $content = json_decode($response->getContent(), true); + $this->assertIsArray($content); + $this->assertEquals(Response::HTTP_OK, $response->getStatusCode()); + $this->assertEquals('Update term', $content['term']); + } + + public function testUpdateATermThatNotExists(): void + { + $response = $this->client->request(Request::METHOD_PATCH, self::BASE_URL.'/999', [ + 'body' => json_encode([ + 'term' => 'Update', + ]), + ]); + + $this->assertEquals(Response::HTTP_NOT_FOUND, $response->getStatusCode()); + } + + /** + * @dataProvider termDataProvider + */ + public function testTermValidations(array $termData, array $expectedMessages): void + { + $this->validateTerm($termData, $expectedMessages); + } + + private function validateTerm(array $termData, array $expectedMessages): void + { + $response = $this->client->request(Request::METHOD_POST, self::BASE_URL, [ + 'json' => $termData, + ]); + + $statusCode = $response->getStatusCode(); + $responseData = $response->toArray(false); + + $this->assertEquals(Response::HTTP_BAD_REQUEST, $statusCode); + $this->assertEquals('The provided data violates one or more constraints.', $responseData['error']); + + $actualMessages = array_map(function ($fieldError) { + return $fieldError['message']; + }, $responseData['fields']); + + $this->assertEquals($expectedMessages, $actualMessages); + } + + public static function termDataProvider(): array + { + return [ + 'blank fields' => [ + 'termData' => [ + 'taxonomy' => '', + 'term' => '', + 'description' => '', + ], + 'expectedMessages' => [ + 'This value should not be blank.', + 'This value is too short. It should have 2 characters or more.', + 'This value should not be blank.', + 'This value is too short. It should have 2 characters or more.', + 'This value should not be blank.', + 'This value is too short. It should have 2 characters or more.', + ], + ], + 'invalid type fields' => [ + 'termData' => [ + 'taxonomy' => 123, + 'term' => 123, + 'description' => 123, + ], + 'expectedMessages' => [ + 'This value should be of type string.', + 'This value should be of type string.', + 'This value should be of type string.', + ], + ], + 'term already exists' => [ + 'termData' => [ + 'taxonomy' => 'existing_taxonomy', + 'term' => 'Arqueologia', + 'description' => 'existing_description', + ], + 'expectedMessages' => [ + 'This value is already used.', + ], + ], + ]; + } +} diff --git a/app/tests/functional/WelcomeApiControllerTest.php b/app/tests/Functional/WelcomeApiControllerTest.php similarity index 95% rename from app/tests/functional/WelcomeApiControllerTest.php rename to app/tests/Functional/WelcomeApiControllerTest.php index 9cc0f7cef5..edab0ae75b 100644 --- a/app/tests/functional/WelcomeApiControllerTest.php +++ b/app/tests/Functional/WelcomeApiControllerTest.php @@ -2,7 +2,9 @@ declare(strict_types=1); -namespace App\Tests; +namespace App\Tests\Functional; + +use App\Tests\AbstractTestCase; class WelcomeApiControllerTest extends AbstractTestCase { diff --git a/app/tests/fixtures/SpaceTestFixtures.php b/app/tests/fixtures/SpaceTestFixtures.php index 97d86583a3..072831bb56 100644 --- a/app/tests/fixtures/SpaceTestFixtures.php +++ b/app/tests/fixtures/SpaceTestFixtures.php @@ -9,33 +9,13 @@ final class SpaceTestFixtures extends AbstractTestFixtures implements TestFixtur public static function partial(): self { return new self([ - 'location' => [ - 'latitude' => '10', - 'longitude' => '10', + 'name' => 'Secretaria da Cultura do Estado do Ceará - SECULT', + 'type' => 41, + 'shortDescription' => 'A Secretaria da Cultura do Estado do Ceará (Secult) foi criada pela Lei nº 8.541, de 9 de agosto de 1966, durante o governo de Virgílio Távora. A Secult tem como missão executar, superintender e coordenar as atividades de proteção do patrimônio cultural do Ceará, difusão da cultura e aprimoramento cultural do povo cearense.', + 'terms' => [ + 'tag' => [], + 'area' => ['Gestão Cultural'], ], - 'name' => 'Espaço da Cultura', - 'public' => true, - 'shortDescription' => 'Um ponto de encontro para compartilhar cultura.', - 'longDescription' => 'Portal que nos transporta para o coração pulsante da rica cultura do brasileiro.', - 'emailPublico' => 'test@test.com', - 'emailPrivado' => 'test@test.com', - 'cnpj' => '00.000.000/0000-00', - 'razaoSocial' => 'Centro Cultural Test', - 'telefonePublico' => '0000-0000', - 'telefone1' => '0000-0000', - 'telefone2' => '0000-0000', - 'acessibilidade' => 'Sim', - 'acessibilidade_fisica' => ['Banheiros adaptados', 'Bebedouro adaptado', 'Circuito de visitação adaptado', 'Rampa de acesso', 'Sanitário adaptado'], - 'capacidade' => 20, - 'endereco' => 'Test', - 'En_CEP' => '80000', - 'En_Nome_Logradouro' => 'Rua test', - 'En_Num' => '1234', - 'En_Complemento' => 'Test', - 'En_Bairro' => 'Test', - 'En_Municipio' => 'Test', - 'En_Estado' => 'CE', - 'horario' => '7:00 - 22:00', ]); } diff --git a/app/tests/fixtures/TermTestFixtures.php b/app/tests/fixtures/TermTestFixtures.php new file mode 100644 index 0000000000..5cdddca711 --- /dev/null +++ b/app/tests/fixtures/TermTestFixtures.php @@ -0,0 +1,22 @@ + 'category', + 'term' => 'Test Term', + 'description' => 'Test Term Description', + ]); + } + + public static function complete(): array + { + return []; + } +} diff --git a/app/tests/functional/EventApiControllerTest.php b/app/tests/functional/EventApiControllerTest.php deleted file mode 100644 index 2e39839a45..0000000000 --- a/app/tests/functional/EventApiControllerTest.php +++ /dev/null @@ -1,104 +0,0 @@ -client->request(Request::METHOD_GET, self::BASE_URL.'/types'); - $content = json_decode($response->getContent()); - - $this->assertEquals(Response::HTTP_OK, $response->getStatusCode()); - $this->assertIsArray($content); - } - - public function testGetOneAgentShouldRetrieveAObject(): void - { - $response = $this->client->request(Request::METHOD_GET, self::BASE_URL.'/1'); - $content = json_decode($response->getContent()); - - $this->assertEquals(Response::HTTP_OK, $response->getStatusCode()); - $this->assertIsObject($content); - } - - public function testGetEventsBySpacesShouldRetrieveAList(): void - { - $this->markTestSkipped(); - $response = $this->client->request(Request::METHOD_GET, '/api/v2/spaces/4/events'); - $content = json_decode($response->getContent()); - - $this->assertEquals(Response::HTTP_OK, $response->getStatusCode()); - $this->assertIsArray($content); - } - - public function testPostEventShouldCreateANewEvent(): void - { - $this->markTestSkipped(); - $eventTestFixtures = EventTestFixtures::partial(); - - $response = $this->client->request(Request::METHOD_POST, self::BASE_URL, [ - 'body' => $eventTestFixtures->json(), - ]); - $content = json_decode($response->getContent()); - - $this->assertEquals(Response::HTTP_CREATED, $response->getStatusCode()); - $this->assertIsObject($content); - } - - public function testDeleteEventShouldRemoveAnEvent(): void - { - $this->markTestSkipped(); - $response = $this->client->request(Request::METHOD_DELETE, self::BASE_URL.'/1'); - $content = json_decode($response->getContent()); - - $this->assertEquals(Response::HTTP_OK, $response->getStatusCode()); - $this->assertIsArray($content); - } - - public function testUpdateEventShouldUpdateAnEvent(): void - { - $eventTestFixtures = EventTestFixtures::partial(); - - $url = sprintf(self::BASE_URL.'/%s', EventFixtures::EVENT_ID_2); - - $response = $this->client->request(Request::METHOD_PATCH, $url, [ - 'body' => $eventTestFixtures->json(), - ]); - - $content = json_decode($response->getContent(), true); - $this->assertEquals(Response::HTTP_CREATED, $response->getStatusCode()); - $this->assertIsArray($content); - foreach ($eventTestFixtures->toArray() as $key => $value) { - $this->assertEquals($value, $content[$key]); - } - } - - public function testUpdateNotFoundedEventResource(): void - { - $eventTestFixtures = EventTestFixtures::partial(); - $url = sprintf(self::BASE_URL.'/%s', 1024); - - $response = $this->client->request(Request::METHOD_PATCH, $url, [ - 'body' => $eventTestFixtures->json(), - ]); - - $error = [ - 'error' => 'Event not found or already deleted.', - ]; - - $content = json_decode($response->getContent(false), true); - $this->assertEquals(Response::HTTP_BAD_REQUEST, $response->getStatusCode()); - $this->assertIsArray($content); - $this->assertEquals($error, $content); - } -} diff --git a/app/tests/functional/TermApiControllerTest.php b/app/tests/functional/TermApiControllerTest.php deleted file mode 100644 index 7721424574..0000000000 --- a/app/tests/functional/TermApiControllerTest.php +++ /dev/null @@ -1,31 +0,0 @@ -client->request(Request::METHOD_GET, self::BASE_URL); - $content = json_decode($response->getContent()); - - $this->assertEquals(Response::HTTP_OK, $response->getStatusCode()); - $this->assertIsArray($content); - } - - public function testGetOneTermShouldRetrieveAObject(): void - { - $response = $this->client->request(Request::METHOD_GET, self::BASE_URL.'/1'); - $content = json_decode($response->getContent()); - - $this->assertEquals(Response::HTTP_OK, $response->getStatusCode()); - $this->assertIsObject($content); - } -} diff --git a/composer.json b/composer.json index 96b483ece9..29f15d1c82 100644 --- a/composer.json +++ b/composer.json @@ -6,10 +6,13 @@ "type": "project", "license": "AGPL", "require-dev": { - "phpunit/phpunit": "^10.5", "squizlabs/php_codesniffer": "3.*", "vimeo/psalm": "^5.17", - "zircote/swagger-php": "^4.8" + "zircote/swagger-php": "^4.8", + "friendsofphp/php-cs-fixer": "^3.51", + "phpunit/phpunit": "^10", + "symfony/http-client": "^7", + "doctrine/data-fixtures": "^1.7" }, "require": { "php": "^7.3 || ^8", @@ -19,8 +22,7 @@ "doctrine/annotations": "^2.0", "doctrine/dbal": "^3.6", "doctrine/orm": "2.16.*", - "firebase/php-jwt": "^6.4", - "league/csv": "^9.6.2", + "firebase/php-jwt": "^6.10", "michelf/php-markdown": "1.*", "monolog/monolog": "^3.4", "mustache/mustache": "^2.11", @@ -43,15 +45,17 @@ "symfony/mailgun-mailer": "^6.3", "symfony/mime": "^6.3", "symfony/sendgrid-mailer": "^6.3", - "league/csv": "^9.6.2", "symfony/http-foundation": "^7.0", "symfony/routing": "^7.0", - "symfony/console": "^6.4.6", "symfony/serializer": "^7.0", "symfony/property-access": "^7.0", "symfony/validator": "^7.0", "symfony/console": "^6.4.6", - "league/csv": "^9.6.2" + "league/csv": "^9.6.2", + "php-di/php-di": "^7.0", + "symfony/dotenv": "^7.1", + "doctrine/migrations": "^3.8", + "symfony/yaml": "^7.1" }, "autoload": { "psr-4": { @@ -81,11 +85,5 @@ "type": "git", "url": "https://github.com/mapasculturais/opauth.git" } - ], - "require-dev": { - "friendsofphp/php-cs-fixer": "^3.51", - "phpunit/phpunit": "^10", - "symfony/http-client": "^7", - "doctrine/data-fixtures": "^1.7" - } + ] } diff --git a/composer.lock b/composer.lock index c5d434ea57..7fb5bb1e42 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "7febe59ff68e42b1f5c10d67356bbf4d", + "content-hash": "98188059823a7a56fa8266fa929bb193", "packages": [ { "name": "acelaya/doctrine-enum-type", @@ -74,20 +74,21 @@ }, { "name": "akrabat/ip-address-middleware", - "version": "2.2.0", + "version": "2.3.0", "source": { "type": "git", "url": "https://github.com/akrabat/ip-address-middleware.git", - "reference": "5e3b94b9c29c8e0cde80941bb87d6a68a6532b9d" + "reference": "651996c90d4a175b6cf73a626535b4f21b7e3679" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/akrabat/ip-address-middleware/zipball/5e3b94b9c29c8e0cde80941bb87d6a68a6532b9d", - "reference": "5e3b94b9c29c8e0cde80941bb87d6a68a6532b9d", + "url": "https://api.github.com/repos/akrabat/ip-address-middleware/zipball/651996c90d4a175b6cf73a626535b4f21b7e3679", + "reference": "651996c90d4a175b6cf73a626535b4f21b7e3679", "shasum": "" }, "require": { "php": "^7.2 || ^8.0", + "psr/container": "^1.0 || ^2.0", "psr/http-message": "^1.0 || ^2.0", "psr/http-server-middleware": "^1.0" }, @@ -100,6 +101,11 @@ "squizlabs/php_codesniffer": "^3.2" }, "type": "library", + "extra": { + "laminas": { + "config-provider": "RKA\\Middleware\\Mezzio\\ConfigProvider" + } + }, "autoload": { "psr-4": { "RKA\\Middleware\\": "src" @@ -125,22 +131,22 @@ ], "support": { "issues": "https://github.com/akrabat/ip-address-middleware/issues", - "source": "https://github.com/akrabat/ip-address-middleware/tree/2.2.0" + "source": "https://github.com/akrabat/ip-address-middleware/tree/2.3.0" }, - "time": "2024-06-09T13:39:46+00:00" + "time": "2024-07-15T17:53:04+00:00" }, { "name": "async-aws/core", - "version": "1.21.0", + "version": "1.22.0", "source": { "type": "git", "url": "https://github.com/async-aws/core.git", - "reference": "eb23cc59515d8d529163313bbf9e02f666e515ef" + "reference": "cbd7012890a35a9b21f7235817a627488709551b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/async-aws/core/zipball/eb23cc59515d8d529163313bbf9e02f666e515ef", - "reference": "eb23cc59515d8d529163313bbf9e02f666e515ef", + "url": "https://api.github.com/repos/async-aws/core/zipball/cbd7012890a35a9b21f7235817a627488709551b", + "reference": "cbd7012890a35a9b21f7235817a627488709551b", "shasum": "" }, "require": { @@ -162,7 +168,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.21-dev" + "dev-master": "1.22-dev" } }, "autoload": { @@ -183,7 +189,7 @@ "sts" ], "support": { - "source": "https://github.com/async-aws/core/tree/1.21.0" + "source": "https://github.com/async-aws/core/tree/1.22.0" }, "funding": [ { @@ -195,20 +201,20 @@ "type": "github" } ], - "time": "2024-02-27T14:44:12+00:00" + "time": "2024-07-03T17:28:59+00:00" }, { "name": "async-aws/ses", - "version": "1.8.0", + "version": "1.8.1", "source": { "type": "git", "url": "https://github.com/async-aws/ses.git", - "reference": "9bf4873210cfc8b86e4abb18d1d707f9ae247ace" + "reference": "7917c218ab27f6602e6f581bc5f4a54fb0e67dc6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/async-aws/ses/zipball/9bf4873210cfc8b86e4abb18d1d707f9ae247ace", - "reference": "9bf4873210cfc8b86e4abb18d1d707f9ae247ace", + "url": "https://api.github.com/repos/async-aws/ses/zipball/7917c218ab27f6602e6f581bc5f4a54fb0e67dc6", + "reference": "7917c218ab27f6602e6f581bc5f4a54fb0e67dc6", "shasum": "" }, "require": { @@ -240,7 +246,7 @@ "ses" ], "support": { - "source": "https://github.com/async-aws/ses/tree/1.8.0" + "source": "https://github.com/async-aws/ses/tree/1.8.1" }, "funding": [ { @@ -252,7 +258,7 @@ "type": "github" } ], - "time": "2024-05-14T07:34:42+00:00" + "time": "2024-07-03T17:28:59+00:00" }, { "name": "creof/doctrine2-spatial", @@ -1321,6 +1327,108 @@ ], "time": "2024-02-05T11:35:39+00:00" }, + { + "name": "doctrine/migrations", + "version": "3.8.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/migrations.git", + "reference": "535a70dcbd88b8c6ba945be050977457f4f4c06c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/migrations/zipball/535a70dcbd88b8c6ba945be050977457f4f4c06c", + "reference": "535a70dcbd88b8c6ba945be050977457f4f4c06c", + "shasum": "" + }, + "require": { + "composer-runtime-api": "^2", + "doctrine/dbal": "^3.6 || ^4", + "doctrine/deprecations": "^0.5.3 || ^1", + "doctrine/event-manager": "^1.2 || ^2.0", + "php": "^8.1", + "psr/log": "^1.1.3 || ^2 || ^3", + "symfony/console": "^5.4 || ^6.0 || ^7.0", + "symfony/stopwatch": "^5.4 || ^6.0 || ^7.0", + "symfony/var-exporter": "^6.2 || ^7.0" + }, + "conflict": { + "doctrine/orm": "<2.12 || >=4" + }, + "require-dev": { + "doctrine/coding-standard": "^12", + "doctrine/orm": "^2.13 || ^3", + "doctrine/persistence": "^2 || ^3", + "doctrine/sql-formatter": "^1.0", + "ext-pdo_sqlite": "*", + "phpstan/phpstan": "^1.10", + "phpstan/phpstan-deprecation-rules": "^1.1", + "phpstan/phpstan-phpunit": "^1.3", + "phpstan/phpstan-strict-rules": "^1.4", + "phpstan/phpstan-symfony": "^1.3", + "phpunit/phpunit": "^10.3", + "symfony/cache": "^5.4 || ^6.0 || ^7.0", + "symfony/process": "^5.4 || ^6.0 || ^7.0", + "symfony/yaml": "^5.4 || ^6.0 || ^7.0" + }, + "suggest": { + "doctrine/sql-formatter": "Allows to generate formatted SQL with the diff command.", + "symfony/yaml": "Allows the use of yaml for migration configuration files." + }, + "bin": [ + "bin/doctrine-migrations" + ], + "type": "library", + "autoload": { + "psr-4": { + "Doctrine\\Migrations\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Michael Simonson", + "email": "contact@mikesimonson.com" + } + ], + "description": "PHP Doctrine Migrations project offer additional functionality on top of the database abstraction layer (DBAL) for versioning your database schema and easily deploying changes to it. It is a very easy to use and a powerful tool.", + "homepage": "https://www.doctrine-project.org/projects/migrations.html", + "keywords": [ + "database", + "dbal", + "migrations" + ], + "support": { + "issues": "https://github.com/doctrine/migrations/issues", + "source": "https://github.com/doctrine/migrations/tree/3.8.0" + }, + "funding": [ + { + "url": "https://www.doctrine-project.org/sponsorship.html", + "type": "custom" + }, + { + "url": "https://www.patreon.com/phpdoctrine", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/doctrine%2Fmigrations", + "type": "tidelift" + } + ], + "time": "2024-06-26T14:12:46+00:00" + }, { "name": "doctrine/orm", "version": "2.16.3", @@ -1705,6 +1813,66 @@ }, "time": "2024-05-18T18:05:11+00:00" }, + { + "name": "laravel/serializable-closure", + "version": "v1.3.3", + "source": { + "type": "git", + "url": "https://github.com/laravel/serializable-closure.git", + "reference": "3dbf8a8e914634c48d389c1234552666b3d43754" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/laravel/serializable-closure/zipball/3dbf8a8e914634c48d389c1234552666b3d43754", + "reference": "3dbf8a8e914634c48d389c1234552666b3d43754", + "shasum": "" + }, + "require": { + "php": "^7.3|^8.0" + }, + "require-dev": { + "nesbot/carbon": "^2.61", + "pestphp/pest": "^1.21.3", + "phpstan/phpstan": "^1.8.2", + "symfony/var-dumper": "^5.4.11" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Laravel\\SerializableClosure\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + }, + { + "name": "Nuno Maduro", + "email": "nuno@laravel.com" + } + ], + "description": "Laravel Serializable Closure provides an easy and secure way to serialize closures in PHP.", + "keywords": [ + "closure", + "laravel", + "serializable" + ], + "support": { + "issues": "https://github.com/laravel/serializable-closure/issues", + "source": "https://github.com/laravel/serializable-closure" + }, + "time": "2023-11-08T14:08:06+00:00" + }, { "name": "league/csv", "version": "9.16.0", @@ -2494,6 +2662,134 @@ }, "time": "2024-04-09T18:03:13+00:00" }, + { + "name": "php-di/invoker", + "version": "2.3.4", + "source": { + "type": "git", + "url": "https://github.com/PHP-DI/Invoker.git", + "reference": "33234b32dafa8eb69202f950a1fc92055ed76a86" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/PHP-DI/Invoker/zipball/33234b32dafa8eb69202f950a1fc92055ed76a86", + "reference": "33234b32dafa8eb69202f950a1fc92055ed76a86", + "shasum": "" + }, + "require": { + "php": ">=7.3", + "psr/container": "^1.0|^2.0" + }, + "require-dev": { + "athletic/athletic": "~0.1.8", + "mnapoli/hard-mode": "~0.3.0", + "phpunit/phpunit": "^9.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Invoker\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Generic and extensible callable invoker", + "homepage": "https://github.com/PHP-DI/Invoker", + "keywords": [ + "callable", + "dependency", + "dependency-injection", + "injection", + "invoke", + "invoker" + ], + "support": { + "issues": "https://github.com/PHP-DI/Invoker/issues", + "source": "https://github.com/PHP-DI/Invoker/tree/2.3.4" + }, + "funding": [ + { + "url": "https://github.com/mnapoli", + "type": "github" + } + ], + "time": "2023-09-08T09:24:21+00:00" + }, + { + "name": "php-di/php-di", + "version": "7.0.7", + "source": { + "type": "git", + "url": "https://github.com/PHP-DI/PHP-DI.git", + "reference": "e87435e3c0e8f22977adc5af0d5cdcc467e15cf1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/PHP-DI/PHP-DI/zipball/e87435e3c0e8f22977adc5af0d5cdcc467e15cf1", + "reference": "e87435e3c0e8f22977adc5af0d5cdcc467e15cf1", + "shasum": "" + }, + "require": { + "laravel/serializable-closure": "^1.0", + "php": ">=8.0", + "php-di/invoker": "^2.0", + "psr/container": "^1.1 || ^2.0" + }, + "provide": { + "psr/container-implementation": "^1.0" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "^3", + "friendsofphp/proxy-manager-lts": "^1", + "mnapoli/phpunit-easymock": "^1.3", + "phpunit/phpunit": "^9.5", + "vimeo/psalm": "^4.6" + }, + "suggest": { + "friendsofphp/proxy-manager-lts": "Install it if you want to use lazy injection (version ^1)" + }, + "type": "library", + "autoload": { + "files": [ + "src/functions.php" + ], + "psr-4": { + "DI\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "The dependency injection container for humans", + "homepage": "https://php-di.org/", + "keywords": [ + "PSR-11", + "container", + "container-interop", + "dependency injection", + "di", + "ioc", + "psr11" + ], + "support": { + "issues": "https://github.com/PHP-DI/PHP-DI/issues", + "source": "https://github.com/PHP-DI/PHP-DI/tree/7.0.7" + }, + "funding": [ + { + "url": "https://github.com/mnapoli", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/php-di/php-di", + "type": "tidelift" + } + ], + "time": "2024-07-21T15:55:45+00:00" + }, { "name": "pomo/pomo", "version": "v1.5.0", @@ -3921,6 +4217,80 @@ ], "time": "2024-04-18T09:32:20+00:00" }, + { + "name": "symfony/dotenv", + "version": "v7.1.1", + "source": { + "type": "git", + "url": "https://github.com/symfony/dotenv.git", + "reference": "efa715ec40c098f2fba62444f4fd75d0d4248ede" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/dotenv/zipball/efa715ec40c098f2fba62444f4fd75d0d4248ede", + "reference": "efa715ec40c098f2fba62444f4fd75d0d4248ede", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "conflict": { + "symfony/console": "<6.4", + "symfony/process": "<6.4" + }, + "require-dev": { + "symfony/console": "^6.4|^7.0", + "symfony/process": "^6.4|^7.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Dotenv\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Registers environment variables from a .env file", + "homepage": "https://symfony.com", + "keywords": [ + "dotenv", + "env", + "environment" + ], + "support": { + "source": "https://github.com/symfony/dotenv/tree/v7.1.1" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-05-31T14:57:53+00:00" + }, { "name": "symfony/event-dispatcher", "version": "v7.1.1", @@ -5748,11 +6118,73 @@ "time": "2024-04-18T09:32:20+00:00" }, { - "name": "symfony/string", - "version": "v7.1.2", + "name": "symfony/stopwatch", + "version": "v7.1.1", "source": { "type": "git", - "url": "https://github.com/symfony/string.git", + "url": "https://github.com/symfony/stopwatch.git", + "reference": "5b75bb1ac2ba1b9d05c47fc4b3046a625377d23d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/stopwatch/zipball/5b75bb1ac2ba1b9d05c47fc4b3046a625377d23d", + "reference": "5b75bb1ac2ba1b9d05c47fc4b3046a625377d23d", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "symfony/service-contracts": "^2.5|^3" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Stopwatch\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides a way to profile code", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/stopwatch/tree/v7.1.1" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-05-31T14:57:53+00:00" + }, + { + "name": "symfony/string", + "version": "v7.1.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/string.git", "reference": "14221089ac66cf82e3cf3d1c1da65de305587ff8" }, "dist": { @@ -6251,9 +6683,240 @@ } ], "time": "2024-06-28T08:00:31+00:00" + }, + { + "name": "symfony/yaml", + "version": "v7.1.1", + "source": { + "type": "git", + "url": "https://github.com/symfony/yaml.git", + "reference": "fa34c77015aa6720469db7003567b9f772492bf2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/yaml/zipball/fa34c77015aa6720469db7003567b9f772492bf2", + "reference": "fa34c77015aa6720469db7003567b9f772492bf2", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "symfony/polyfill-ctype": "^1.8" + }, + "conflict": { + "symfony/console": "<6.4" + }, + "require-dev": { + "symfony/console": "^6.4|^7.0" + }, + "bin": [ + "Resources/bin/yaml-lint" + ], + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Yaml\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Loads and dumps YAML files", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/yaml/tree/v7.1.1" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-05-31T14:57:53+00:00" } ], "packages-dev": [ + { + "name": "amphp/amp", + "version": "v2.6.4", + "source": { + "type": "git", + "url": "https://github.com/amphp/amp.git", + "reference": "ded3d9be08f526089eb7ee8d9f16a9768f9dec2d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/amphp/amp/zipball/ded3d9be08f526089eb7ee8d9f16a9768f9dec2d", + "reference": "ded3d9be08f526089eb7ee8d9f16a9768f9dec2d", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "require-dev": { + "amphp/php-cs-fixer-config": "dev-master", + "amphp/phpunit-util": "^1", + "ext-json": "*", + "jetbrains/phpstorm-stubs": "^2019.3", + "phpunit/phpunit": "^7 | ^8 | ^9", + "react/promise": "^2", + "vimeo/psalm": "^3.12" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.x-dev" + } + }, + "autoload": { + "files": [ + "lib/functions.php", + "lib/Internal/functions.php" + ], + "psr-4": { + "Amp\\": "lib" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Daniel Lowrey", + "email": "rdlowrey@php.net" + }, + { + "name": "Aaron Piotrowski", + "email": "aaron@trowski.com" + }, + { + "name": "Bob Weinand", + "email": "bobwei9@hotmail.com" + }, + { + "name": "Niklas Keller", + "email": "me@kelunik.com" + } + ], + "description": "A non-blocking concurrency framework for PHP applications.", + "homepage": "https://amphp.org/amp", + "keywords": [ + "async", + "asynchronous", + "awaitable", + "concurrency", + "event", + "event-loop", + "future", + "non-blocking", + "promise" + ], + "support": { + "irc": "irc://irc.freenode.org/amphp", + "issues": "https://github.com/amphp/amp/issues", + "source": "https://github.com/amphp/amp/tree/v2.6.4" + }, + "funding": [ + { + "url": "https://github.com/amphp", + "type": "github" + } + ], + "time": "2024-03-21T18:52:26+00:00" + }, + { + "name": "amphp/byte-stream", + "version": "v1.8.2", + "source": { + "type": "git", + "url": "https://github.com/amphp/byte-stream.git", + "reference": "4f0e968ba3798a423730f567b1b50d3441c16ddc" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/amphp/byte-stream/zipball/4f0e968ba3798a423730f567b1b50d3441c16ddc", + "reference": "4f0e968ba3798a423730f567b1b50d3441c16ddc", + "shasum": "" + }, + "require": { + "amphp/amp": "^2", + "php": ">=7.1" + }, + "require-dev": { + "amphp/php-cs-fixer-config": "dev-master", + "amphp/phpunit-util": "^1.4", + "friendsofphp/php-cs-fixer": "^2.3", + "jetbrains/phpstorm-stubs": "^2019.3", + "phpunit/phpunit": "^6 || ^7 || ^8", + "psalm/phar": "^3.11.4" + }, + "type": "library", + "autoload": { + "files": [ + "lib/functions.php" + ], + "psr-4": { + "Amp\\ByteStream\\": "lib" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Aaron Piotrowski", + "email": "aaron@trowski.com" + }, + { + "name": "Niklas Keller", + "email": "me@kelunik.com" + } + ], + "description": "A stream abstraction to make working with non-blocking I/O simple.", + "homepage": "https://amphp.org/byte-stream", + "keywords": [ + "amp", + "amphp", + "async", + "io", + "non-blocking", + "stream" + ], + "support": { + "issues": "https://github.com/amphp/byte-stream/issues", + "source": "https://github.com/amphp/byte-stream/tree/v1.8.2" + }, + "funding": [ + { + "url": "https://github.com/amphp", + "type": "github" + } + ], + "time": "2024-04-13T18:00:56+00:00" + }, { "name": "clue/ndjson-react", "version": "v1.3.0", @@ -6391,16 +7054,16 @@ }, { "name": "composer/semver", - "version": "3.4.0", + "version": "3.4.2", "source": { "type": "git", "url": "https://github.com/composer/semver.git", - "reference": "35e8d0af4486141bc745f23a29cc2091eb624a32" + "reference": "c51258e759afdb17f1fd1fe83bc12baaef6309d6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/semver/zipball/35e8d0af4486141bc745f23a29cc2091eb624a32", - "reference": "35e8d0af4486141bc745f23a29cc2091eb624a32", + "url": "https://api.github.com/repos/composer/semver/zipball/c51258e759afdb17f1fd1fe83bc12baaef6309d6", + "reference": "c51258e759afdb17f1fd1fe83bc12baaef6309d6", "shasum": "" }, "require": { @@ -6452,7 +7115,7 @@ "support": { "irc": "ircs://irc.libera.chat:6697/composer", "issues": "https://github.com/composer/semver/issues", - "source": "https://github.com/composer/semver/tree/3.4.0" + "source": "https://github.com/composer/semver/tree/3.4.2" }, "funding": [ { @@ -6468,7 +7131,7 @@ "type": "tidelift" } ], - "time": "2023-08-31T09:50:34+00:00" + "time": "2024-07-12T11:35:52+00:00" }, { "name": "composer/xdebug-handler", @@ -6536,6 +7199,43 @@ ], "time": "2024-05-06T16:37:16+00:00" }, + { + "name": "dnoegel/php-xdg-base-dir", + "version": "v0.1.1", + "source": { + "type": "git", + "url": "https://github.com/dnoegel/php-xdg-base-dir.git", + "reference": "8f8a6e48c5ecb0f991c2fdcf5f154a47d85f9ffd" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/dnoegel/php-xdg-base-dir/zipball/8f8a6e48c5ecb0f991c2fdcf5f154a47d85f9ffd", + "reference": "8f8a6e48c5ecb0f991c2fdcf5f154a47d85f9ffd", + "shasum": "" + }, + "require": { + "php": ">=5.3.2" + }, + "require-dev": { + "phpunit/phpunit": "~7.0|~6.0|~5.0|~4.8.35" + }, + "type": "library", + "autoload": { + "psr-4": { + "XdgBaseDir\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "implementation of xdg base directory specification for php", + "support": { + "issues": "https://github.com/dnoegel/php-xdg-base-dir/issues", + "source": "https://github.com/dnoegel/php-xdg-base-dir/tree/v0.1.1" + }, + "time": "2019-12-04T15:06:13+00:00" + }, { "name": "doctrine/data-fixtures", "version": "1.7.0", @@ -6668,28 +7368,129 @@ "time": "2023-08-08T05:53:35+00:00" }, { - "name": "fidry/cpu-core-counter", - "version": "1.1.0", + "name": "felixfbecker/advanced-json-rpc", + "version": "v3.2.1", "source": { "type": "git", - "url": "https://github.com/theofidry/cpu-core-counter.git", - "reference": "f92996c4d5c1a696a6a970e20f7c4216200fcc42" + "url": "https://github.com/felixfbecker/php-advanced-json-rpc.git", + "reference": "b5f37dbff9a8ad360ca341f3240dc1c168b45447" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/theofidry/cpu-core-counter/zipball/f92996c4d5c1a696a6a970e20f7c4216200fcc42", - "reference": "f92996c4d5c1a696a6a970e20f7c4216200fcc42", + "url": "https://api.github.com/repos/felixfbecker/php-advanced-json-rpc/zipball/b5f37dbff9a8ad360ca341f3240dc1c168b45447", + "reference": "b5f37dbff9a8ad360ca341f3240dc1c168b45447", "shasum": "" }, "require": { - "php": "^7.2 || ^8.0" + "netresearch/jsonmapper": "^1.0 || ^2.0 || ^3.0 || ^4.0", + "php": "^7.1 || ^8.0", + "phpdocumentor/reflection-docblock": "^4.3.4 || ^5.0.0" }, "require-dev": { - "fidry/makefile": "^0.2.0", - "fidry/php-cs-fixer-config": "^1.1.2", - "phpstan/extension-installer": "^1.2.0", - "phpstan/phpstan": "^1.9.2", - "phpstan/phpstan-deprecation-rules": "^1.0.0", + "phpunit/phpunit": "^7.0 || ^8.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "AdvancedJsonRpc\\": "lib/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "ISC" + ], + "authors": [ + { + "name": "Felix Becker", + "email": "felix.b@outlook.com" + } + ], + "description": "A more advanced JSONRPC implementation", + "support": { + "issues": "https://github.com/felixfbecker/php-advanced-json-rpc/issues", + "source": "https://github.com/felixfbecker/php-advanced-json-rpc/tree/v3.2.1" + }, + "time": "2021-06-11T22:34:44+00:00" + }, + { + "name": "felixfbecker/language-server-protocol", + "version": "v1.5.2", + "source": { + "type": "git", + "url": "https://github.com/felixfbecker/php-language-server-protocol.git", + "reference": "6e82196ffd7c62f7794d778ca52b69feec9f2842" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/felixfbecker/php-language-server-protocol/zipball/6e82196ffd7c62f7794d778ca52b69feec9f2842", + "reference": "6e82196ffd7c62f7794d778ca52b69feec9f2842", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "require-dev": { + "phpstan/phpstan": "*", + "squizlabs/php_codesniffer": "^3.1", + "vimeo/psalm": "^4.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "LanguageServerProtocol\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "ISC" + ], + "authors": [ + { + "name": "Felix Becker", + "email": "felix.b@outlook.com" + } + ], + "description": "PHP classes for the Language Server Protocol", + "keywords": [ + "language", + "microsoft", + "php", + "server" + ], + "support": { + "issues": "https://github.com/felixfbecker/php-language-server-protocol/issues", + "source": "https://github.com/felixfbecker/php-language-server-protocol/tree/v1.5.2" + }, + "time": "2022-03-02T22:36:06+00:00" + }, + { + "name": "fidry/cpu-core-counter", + "version": "1.1.0", + "source": { + "type": "git", + "url": "https://github.com/theofidry/cpu-core-counter.git", + "reference": "f92996c4d5c1a696a6a970e20f7c4216200fcc42" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/theofidry/cpu-core-counter/zipball/f92996c4d5c1a696a6a970e20f7c4216200fcc42", + "reference": "f92996c4d5c1a696a6a970e20f7c4216200fcc42", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "require-dev": { + "fidry/makefile": "^0.2.0", + "fidry/php-cs-fixer-config": "^1.1.2", + "phpstan/extension-installer": "^1.2.0", + "phpstan/phpstan": "^1.9.2", + "phpstan/phpstan-deprecation-rules": "^1.0.0", "phpstan/phpstan-phpunit": "^1.2.2", "phpstan/phpstan-strict-rules": "^1.4.4", "phpunit/phpunit": "^8.5.31 || ^9.5.26", @@ -6891,6 +7692,57 @@ ], "time": "2024-06-12T14:39:25+00:00" }, + { + "name": "netresearch/jsonmapper", + "version": "v4.4.1", + "source": { + "type": "git", + "url": "https://github.com/cweiske/jsonmapper.git", + "reference": "132c75c7dd83e45353ebb9c6c9f591952995bbf0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/cweiske/jsonmapper/zipball/132c75c7dd83e45353ebb9c6c9f591952995bbf0", + "reference": "132c75c7dd83e45353ebb9c6c9f591952995bbf0", + "shasum": "" + }, + "require": { + "ext-json": "*", + "ext-pcre": "*", + "ext-reflection": "*", + "ext-spl": "*", + "php": ">=7.1" + }, + "require-dev": { + "phpunit/phpunit": "~7.5 || ~8.0 || ~9.0 || ~10.0", + "squizlabs/php_codesniffer": "~3.5" + }, + "type": "library", + "autoload": { + "psr-0": { + "JsonMapper": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "OSL-3.0" + ], + "authors": [ + { + "name": "Christian Weiske", + "email": "cweiske@cweiske.de", + "homepage": "http://github.com/cweiske/jsonmapper/", + "role": "Developer" + } + ], + "description": "Map nested JSON structures onto PHP classes", + "support": { + "email": "cweiske@cweiske.de", + "issues": "https://github.com/cweiske/jsonmapper/issues", + "source": "https://github.com/cweiske/jsonmapper/tree/v4.4.1" + }, + "time": "2024-01-31T06:18:54+00:00" + }, { "name": "phar-io/manifest", "version": "2.0.4", @@ -7009,6 +7861,228 @@ }, "time": "2022-02-21T01:04:05+00:00" }, + { + "name": "phpdocumentor/reflection-common", + "version": "2.2.0", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/ReflectionCommon.git", + "reference": "1d01c49d4ed62f25aa84a747ad35d5a16924662b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/1d01c49d4ed62f25aa84a747ad35d5a16924662b", + "reference": "1d01c49d4ed62f25aa84a747ad35d5a16924662b", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-2.x": "2.x-dev" + } + }, + "autoload": { + "psr-4": { + "phpDocumentor\\Reflection\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jaap van Otterdijk", + "email": "opensource@ijaap.nl" + } + ], + "description": "Common reflection classes used by phpdocumentor to reflect the code structure", + "homepage": "http://www.phpdoc.org", + "keywords": [ + "FQSEN", + "phpDocumentor", + "phpdoc", + "reflection", + "static analysis" + ], + "support": { + "issues": "https://github.com/phpDocumentor/ReflectionCommon/issues", + "source": "https://github.com/phpDocumentor/ReflectionCommon/tree/2.x" + }, + "time": "2020-06-27T09:03:43+00:00" + }, + { + "name": "phpdocumentor/reflection-docblock", + "version": "5.4.1", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", + "reference": "9d07b3f7fdcf5efec5d1609cba3c19c5ea2bdc9c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/9d07b3f7fdcf5efec5d1609cba3c19c5ea2bdc9c", + "reference": "9d07b3f7fdcf5efec5d1609cba3c19c5ea2bdc9c", + "shasum": "" + }, + "require": { + "doctrine/deprecations": "^1.1", + "ext-filter": "*", + "php": "^7.4 || ^8.0", + "phpdocumentor/reflection-common": "^2.2", + "phpdocumentor/type-resolver": "^1.7", + "phpstan/phpdoc-parser": "^1.7", + "webmozart/assert": "^1.9.1" + }, + "require-dev": { + "mockery/mockery": "~1.3.5", + "phpstan/extension-installer": "^1.1", + "phpstan/phpstan": "^1.8", + "phpstan/phpstan-mockery": "^1.1", + "phpstan/phpstan-webmozart-assert": "^1.2", + "phpunit/phpunit": "^9.5", + "vimeo/psalm": "^5.13" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.x-dev" + } + }, + "autoload": { + "psr-4": { + "phpDocumentor\\Reflection\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mike van Riel", + "email": "me@mikevanriel.com" + }, + { + "name": "Jaap van Otterdijk", + "email": "opensource@ijaap.nl" + } + ], + "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", + "support": { + "issues": "https://github.com/phpDocumentor/ReflectionDocBlock/issues", + "source": "https://github.com/phpDocumentor/ReflectionDocBlock/tree/5.4.1" + }, + "time": "2024-05-21T05:55:05+00:00" + }, + { + "name": "phpdocumentor/type-resolver", + "version": "1.8.2", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/TypeResolver.git", + "reference": "153ae662783729388a584b4361f2545e4d841e3c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/153ae662783729388a584b4361f2545e4d841e3c", + "reference": "153ae662783729388a584b4361f2545e4d841e3c", + "shasum": "" + }, + "require": { + "doctrine/deprecations": "^1.0", + "php": "^7.3 || ^8.0", + "phpdocumentor/reflection-common": "^2.0", + "phpstan/phpdoc-parser": "^1.13" + }, + "require-dev": { + "ext-tokenizer": "*", + "phpbench/phpbench": "^1.2", + "phpstan/extension-installer": "^1.1", + "phpstan/phpstan": "^1.8", + "phpstan/phpstan-phpunit": "^1.1", + "phpunit/phpunit": "^9.5", + "rector/rector": "^0.13.9", + "vimeo/psalm": "^4.25" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-1.x": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "phpDocumentor\\Reflection\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mike van Riel", + "email": "me@mikevanriel.com" + } + ], + "description": "A PSR-5 based resolver of Class names, Types and Structural Element Names", + "support": { + "issues": "https://github.com/phpDocumentor/TypeResolver/issues", + "source": "https://github.com/phpDocumentor/TypeResolver/tree/1.8.2" + }, + "time": "2024-02-23T11:10:43+00:00" + }, + { + "name": "phpstan/phpdoc-parser", + "version": "1.29.1", + "source": { + "type": "git", + "url": "https://github.com/phpstan/phpdoc-parser.git", + "reference": "fcaefacf2d5c417e928405b71b400d4ce10daaf4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/fcaefacf2d5c417e928405b71b400d4ce10daaf4", + "reference": "fcaefacf2d5c417e928405b71b400d4ce10daaf4", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "require-dev": { + "doctrine/annotations": "^2.0", + "nikic/php-parser": "^4.15", + "php-parallel-lint/php-parallel-lint": "^1.2", + "phpstan/extension-installer": "^1.0", + "phpstan/phpstan": "^1.5", + "phpstan/phpstan-phpunit": "^1.1", + "phpstan/phpstan-strict-rules": "^1.0", + "phpunit/phpunit": "^9.5", + "symfony/process": "^5.2" + }, + "type": "library", + "autoload": { + "psr-4": { + "PHPStan\\PhpDocParser\\": [ + "src/" + ] + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "PHPDoc parser with support for nullable, intersection and generic types", + "support": { + "issues": "https://github.com/phpstan/phpdoc-parser/issues", + "source": "https://github.com/phpstan/phpdoc-parser/tree/1.29.1" + }, + "time": "2024-05-31T08:52:43+00:00" + }, { "name": "phpunit/php-code-coverage", "version": "10.1.15", @@ -7332,16 +8406,16 @@ }, { "name": "phpunit/phpunit", - "version": "10.5.24", + "version": "10.5.28", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "5f124e3e3e561006047b532fd0431bf5bb6b9015" + "reference": "ff7fb85cdf88131b83e721fb2a327b664dbed275" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/5f124e3e3e561006047b532fd0431bf5bb6b9015", - "reference": "5f124e3e3e561006047b532fd0431bf5bb6b9015", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/ff7fb85cdf88131b83e721fb2a327b664dbed275", + "reference": "ff7fb85cdf88131b83e721fb2a327b664dbed275", "shasum": "" }, "require": { @@ -7351,26 +8425,26 @@ "ext-mbstring": "*", "ext-xml": "*", "ext-xmlwriter": "*", - "myclabs/deep-copy": "^1.10.1", - "phar-io/manifest": "^2.0.3", - "phar-io/version": "^3.0.2", + "myclabs/deep-copy": "^1.12.0", + "phar-io/manifest": "^2.0.4", + "phar-io/version": "^3.2.1", "php": ">=8.1", - "phpunit/php-code-coverage": "^10.1.5", - "phpunit/php-file-iterator": "^4.0", - "phpunit/php-invoker": "^4.0", - "phpunit/php-text-template": "^3.0", - "phpunit/php-timer": "^6.0", - "sebastian/cli-parser": "^2.0", - "sebastian/code-unit": "^2.0", - "sebastian/comparator": "^5.0", - "sebastian/diff": "^5.0", - "sebastian/environment": "^6.0", - "sebastian/exporter": "^5.1", - "sebastian/global-state": "^6.0.1", - "sebastian/object-enumerator": "^5.0", - "sebastian/recursion-context": "^5.0", - "sebastian/type": "^4.0", - "sebastian/version": "^4.0" + "phpunit/php-code-coverage": "^10.1.15", + "phpunit/php-file-iterator": "^4.1.0", + "phpunit/php-invoker": "^4.0.0", + "phpunit/php-text-template": "^3.0.1", + "phpunit/php-timer": "^6.0.0", + "sebastian/cli-parser": "^2.0.1", + "sebastian/code-unit": "^2.0.0", + "sebastian/comparator": "^5.0.1", + "sebastian/diff": "^5.1.1", + "sebastian/environment": "^6.1.0", + "sebastian/exporter": "^5.1.2", + "sebastian/global-state": "^6.0.2", + "sebastian/object-enumerator": "^5.0.0", + "sebastian/recursion-context": "^5.0.0", + "sebastian/type": "^4.0.0", + "sebastian/version": "^4.0.1" }, "suggest": { "ext-soap": "To be able to generate mocks based on WSDL files" @@ -7413,7 +8487,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/phpunit/issues", "security": "https://github.com/sebastianbergmann/phpunit/security/policy", - "source": "https://github.com/sebastianbergmann/phpunit/tree/10.5.24" + "source": "https://github.com/sebastianbergmann/phpunit/tree/10.5.28" }, "funding": [ { @@ -7429,7 +8503,7 @@ "type": "tidelift" } ], - "time": "2024-06-20T13:09:54+00:00" + "time": "2024-07-18T14:54:16+00:00" }, { "name": "react/cache", @@ -8878,17 +9952,165 @@ "time": "2023-02-07T11:34:05+00:00" }, { - "name": "symfony/filesystem", - "version": "v7.1.2", + "name": "spatie/array-to-xml", + "version": "3.3.0", "source": { "type": "git", - "url": "https://github.com/symfony/filesystem.git", - "reference": "92a91985250c251de9b947a14bb2c9390b1a562c" + "url": "https://github.com/spatie/array-to-xml.git", + "reference": "f56b220fe2db1ade4c88098d83413ebdfc3bf876" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/92a91985250c251de9b947a14bb2c9390b1a562c", - "reference": "92a91985250c251de9b947a14bb2c9390b1a562c", + "url": "https://api.github.com/repos/spatie/array-to-xml/zipball/f56b220fe2db1ade4c88098d83413ebdfc3bf876", + "reference": "f56b220fe2db1ade4c88098d83413ebdfc3bf876", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "php": "^8.0" + }, + "require-dev": { + "mockery/mockery": "^1.2", + "pestphp/pest": "^1.21", + "spatie/pest-plugin-snapshots": "^1.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Spatie\\ArrayToXml\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Freek Van der Herten", + "email": "freek@spatie.be", + "homepage": "https://freek.dev", + "role": "Developer" + } + ], + "description": "Convert an array to xml", + "homepage": "https://github.com/spatie/array-to-xml", + "keywords": [ + "array", + "convert", + "xml" + ], + "support": { + "source": "https://github.com/spatie/array-to-xml/tree/3.3.0" + }, + "funding": [ + { + "url": "https://spatie.be/open-source/support-us", + "type": "custom" + }, + { + "url": "https://github.com/spatie", + "type": "github" + } + ], + "time": "2024-05-01T10:20:27+00:00" + }, + { + "name": "squizlabs/php_codesniffer", + "version": "3.10.2", + "source": { + "type": "git", + "url": "https://github.com/PHPCSStandards/PHP_CodeSniffer.git", + "reference": "86e5f5dd9a840c46810ebe5ff1885581c42a3017" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/PHPCSStandards/PHP_CodeSniffer/zipball/86e5f5dd9a840c46810ebe5ff1885581c42a3017", + "reference": "86e5f5dd9a840c46810ebe5ff1885581c42a3017", + "shasum": "" + }, + "require": { + "ext-simplexml": "*", + "ext-tokenizer": "*", + "ext-xmlwriter": "*", + "php": ">=5.4.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0 || ^8.0 || ^9.3.4" + }, + "bin": [ + "bin/phpcbf", + "bin/phpcs" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.x-dev" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Greg Sherwood", + "role": "Former lead" + }, + { + "name": "Juliette Reinders Folmer", + "role": "Current lead" + }, + { + "name": "Contributors", + "homepage": "https://github.com/PHPCSStandards/PHP_CodeSniffer/graphs/contributors" + } + ], + "description": "PHP_CodeSniffer tokenizes PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.", + "homepage": "https://github.com/PHPCSStandards/PHP_CodeSniffer", + "keywords": [ + "phpcs", + "standards", + "static analysis" + ], + "support": { + "issues": "https://github.com/PHPCSStandards/PHP_CodeSniffer/issues", + "security": "https://github.com/PHPCSStandards/PHP_CodeSniffer/security/policy", + "source": "https://github.com/PHPCSStandards/PHP_CodeSniffer", + "wiki": "https://github.com/PHPCSStandards/PHP_CodeSniffer/wiki" + }, + "funding": [ + { + "url": "https://github.com/PHPCSStandards", + "type": "github" + }, + { + "url": "https://github.com/jrfnl", + "type": "github" + }, + { + "url": "https://opencollective.com/php_codesniffer", + "type": "open_collective" + } + ], + "time": "2024-07-21T23:26:44+00:00" + }, + { + "name": "symfony/filesystem", + "version": "v7.1.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/filesystem.git", + "reference": "92a91985250c251de9b947a14bb2c9390b1a562c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/92a91985250c251de9b947a14bb2c9390b1a562c", + "reference": "92a91985250c251de9b947a14bb2c9390b1a562c", "shasum": "" }, "require": { @@ -9212,116 +10434,303 @@ "time": "2024-05-31T14:57:53+00:00" }, { - "name": "symfony/stopwatch", - "version": "v7.1.1", + "name": "theseer/tokenizer", + "version": "1.2.3", "source": { "type": "git", - "url": "https://github.com/symfony/stopwatch.git", - "reference": "5b75bb1ac2ba1b9d05c47fc4b3046a625377d23d" + "url": "https://github.com/theseer/tokenizer.git", + "reference": "737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/stopwatch/zipball/5b75bb1ac2ba1b9d05c47fc4b3046a625377d23d", - "reference": "5b75bb1ac2ba1b9d05c47fc4b3046a625377d23d", + "url": "https://api.github.com/repos/theseer/tokenizer/zipball/737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2", + "reference": "737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2", "shasum": "" }, "require": { - "php": ">=8.2", - "symfony/service-contracts": "^2.5|^3" + "ext-dom": "*", + "ext-tokenizer": "*", + "ext-xmlwriter": "*", + "php": "^7.2 || ^8.0" }, "type": "library", "autoload": { - "psr-4": { - "Symfony\\Component\\Stopwatch\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" + "classmap": [ + "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "BSD-3-Clause" ], "authors": [ { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" } ], - "description": "Provides a way to profile code", - "homepage": "https://symfony.com", + "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", "support": { - "source": "https://github.com/symfony/stopwatch/tree/v7.1.1" + "issues": "https://github.com/theseer/tokenizer/issues", + "source": "https://github.com/theseer/tokenizer/tree/1.2.3" }, "funding": [ { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", + "url": "https://github.com/theseer", "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" } ], - "time": "2024-05-31T14:57:53+00:00" + "time": "2024-03-03T12:36:25+00:00" }, { - "name": "theseer/tokenizer", - "version": "1.2.3", + "name": "vimeo/psalm", + "version": "5.25.0", "source": { "type": "git", - "url": "https://github.com/theseer/tokenizer.git", - "reference": "737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2" + "url": "https://github.com/vimeo/psalm.git", + "reference": "01a8eb06b9e9cc6cfb6a320bf9fb14331919d505" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/theseer/tokenizer/zipball/737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2", - "reference": "737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2", + "url": "https://api.github.com/repos/vimeo/psalm/zipball/01a8eb06b9e9cc6cfb6a320bf9fb14331919d505", + "reference": "01a8eb06b9e9cc6cfb6a320bf9fb14331919d505", "shasum": "" }, "require": { + "amphp/amp": "^2.4.2", + "amphp/byte-stream": "^1.5", + "composer-runtime-api": "^2", + "composer/semver": "^1.4 || ^2.0 || ^3.0", + "composer/xdebug-handler": "^2.0 || ^3.0", + "dnoegel/php-xdg-base-dir": "^0.1.1", + "ext-ctype": "*", "ext-dom": "*", + "ext-json": "*", + "ext-libxml": "*", + "ext-mbstring": "*", + "ext-simplexml": "*", "ext-tokenizer": "*", - "ext-xmlwriter": "*", + "felixfbecker/advanced-json-rpc": "^3.1", + "felixfbecker/language-server-protocol": "^1.5.2", + "fidry/cpu-core-counter": "^0.4.1 || ^0.5.1 || ^1.0.0", + "netresearch/jsonmapper": "^1.0 || ^2.0 || ^3.0 || ^4.0", + "nikic/php-parser": "^4.16", + "php": "^7.4 || ~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0", + "sebastian/diff": "^4.0 || ^5.0 || ^6.0", + "spatie/array-to-xml": "^2.17.0 || ^3.0", + "symfony/console": "^4.1.6 || ^5.0 || ^6.0 || ^7.0", + "symfony/filesystem": "^5.4 || ^6.0 || ^7.0" + }, + "conflict": { + "nikic/php-parser": "4.17.0" + }, + "provide": { + "psalm/psalm": "self.version" + }, + "require-dev": { + "amphp/phpunit-util": "^2.0", + "bamarni/composer-bin-plugin": "^1.4", + "brianium/paratest": "^6.9", + "ext-curl": "*", + "mockery/mockery": "^1.5", + "nunomaduro/mock-final-classes": "^1.1", + "php-parallel-lint/php-parallel-lint": "^1.2", + "phpstan/phpdoc-parser": "^1.6", + "phpunit/phpunit": "^9.6", + "psalm/plugin-mockery": "^1.1", + "psalm/plugin-phpunit": "^0.18", + "slevomat/coding-standard": "^8.4", + "squizlabs/php_codesniffer": "^3.6", + "symfony/process": "^4.4 || ^5.0 || ^6.0 || ^7.0" + }, + "suggest": { + "ext-curl": "In order to send data to shepherd", + "ext-igbinary": "^2.0.5 is required, used to serialize caching data" + }, + "bin": [ + "psalm", + "psalm-language-server", + "psalm-plugin", + "psalm-refactor", + "psalter" + ], + "type": "project", + "extra": { + "branch-alias": { + "dev-master": "5.x-dev", + "dev-4.x": "4.x-dev", + "dev-3.x": "3.x-dev", + "dev-2.x": "2.x-dev", + "dev-1.x": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psalm\\": "src/Psalm/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Matthew Brown" + } + ], + "description": "A static analysis tool for finding errors in PHP applications", + "keywords": [ + "code", + "inspection", + "php", + "static analysis" + ], + "support": { + "docs": "https://psalm.dev/docs", + "issues": "https://github.com/vimeo/psalm/issues", + "source": "https://github.com/vimeo/psalm" + }, + "time": "2024-06-16T15:08:35+00:00" + }, + { + "name": "webmozart/assert", + "version": "1.11.0", + "source": { + "type": "git", + "url": "https://github.com/webmozarts/assert.git", + "reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/webmozarts/assert/zipball/11cb2199493b2f8a3b53e7f19068fc6aac760991", + "reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991", + "shasum": "" + }, + "require": { + "ext-ctype": "*", "php": "^7.2 || ^8.0" }, + "conflict": { + "phpstan/phpstan": "<0.12.20", + "vimeo/psalm": "<4.6.1 || 4.6.2" + }, + "require-dev": { + "phpunit/phpunit": "^8.5.13" + }, "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.10-dev" + } + }, "autoload": { - "classmap": [ - "src/" - ] + "psr-4": { + "Webmozart\\Assert\\": "src/" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" + "MIT" ], "authors": [ { - "name": "Arne Blankerts", - "email": "arne@blankerts.de", - "role": "Developer" + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" } ], - "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", + "description": "Assertions to validate method input/output with nice error messages.", + "keywords": [ + "assert", + "check", + "validate" + ], "support": { - "issues": "https://github.com/theseer/tokenizer/issues", - "source": "https://github.com/theseer/tokenizer/tree/1.2.3" + "issues": "https://github.com/webmozarts/assert/issues", + "source": "https://github.com/webmozarts/assert/tree/1.11.0" }, - "funding": [ + "time": "2022-06-03T18:03:27+00:00" + }, + { + "name": "zircote/swagger-php", + "version": "4.10.5", + "source": { + "type": "git", + "url": "https://github.com/zircote/swagger-php.git", + "reference": "0840dad40fd6759912485f34bfccf13b49b29226" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/zircote/swagger-php/zipball/0840dad40fd6759912485f34bfccf13b49b29226", + "reference": "0840dad40fd6759912485f34bfccf13b49b29226", + "shasum": "" + }, + "require": { + "ext-json": "*", + "php": ">=7.2", + "psr/log": "^1.1 || ^2.0 || ^3.0", + "symfony/deprecation-contracts": "^2 || ^3", + "symfony/finder": ">=2.2", + "symfony/yaml": ">=3.3" + }, + "require-dev": { + "composer/package-versions-deprecated": "^1.11", + "doctrine/annotations": "^1.7 || ^2.0", + "friendsofphp/php-cs-fixer": "^2.17 || ^3.47.1", + "phpstan/phpstan": "^1.6", + "phpunit/phpunit": ">=8", + "vimeo/psalm": "^4.23" + }, + "suggest": { + "doctrine/annotations": "^1.7 || ^2.0" + }, + "bin": [ + "bin/openapi" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.x-dev" + } + }, + "autoload": { + "psr-4": { + "OpenApi\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache-2.0" + ], + "authors": [ { - "url": "https://github.com/theseer", - "type": "github" + "name": "Robert Allen", + "email": "zircote@gmail.com" + }, + { + "name": "Bob Fanger", + "email": "bfanger@gmail.com", + "homepage": "https://bfanger.nl" + }, + { + "name": "Martin Rademacher", + "email": "mano@radebatz.net", + "homepage": "https://radebatz.net" } ], - "time": "2024-03-03T12:36:25+00:00" + "description": "swagger-php - Generate interactive documentation for your RESTful API using phpdoc annotations", + "homepage": "https://github.com/zircote/swagger-php/", + "keywords": [ + "api", + "json", + "rest", + "service discovery" + ], + "support": { + "issues": "https://github.com/zircote/swagger-php/issues", + "source": "https://github.com/zircote/swagger-php/tree/4.10.5" + }, + "time": "2024-07-16T03:13:27+00:00" } ], "aliases": [], diff --git a/composer.phar b/composer.phar deleted file mode 100755 index 53f8b81265..0000000000 Binary files a/composer.phar and /dev/null differ diff --git a/help/DEV-FLOW.md b/help/DEV-FLOW.md new file mode 100644 index 0000000000..c8d84cf385 --- /dev/null +++ b/help/DEV-FLOW.md @@ -0,0 +1,150 @@ +# Fluxo de Desenvolvimento + +Todo o desenvolvimento segue um fluxo baseado em Kanban/Scrum/Agile que segue uma sequência lógica para resolução de um **problema** ou implementação de uma nova **funcionalidade** + + +## Issues + +```mermaid +graph TD; + IssueOpened-->Feature; + IssueOpened-->Bug; + IssueOpened-->Adjust; + IssueOpened-->Improvement; + IssueOpened-->Quality; + IssueOpened-->Discovery; + IssueOpened-->Docs; + Feature-->Closed; + Bug-->Closed; + Adjust-->Closed; + Improvement-->Closed; + Docs-->Closed; + Quality-->Closed; + Discovery-->Closed; +``` + +Cada tipo de issue define o tipo de implementação a ser feita no código + +- **Feature:** Novas funcionalidades, normalmente algo que ainda não existe na aplicação +- **Bug:** Problema a ser resolvido, que muito provavelmente impossibilita e/ou atrapalha a execução de alguma ação +- **Adjust:** Pequenas modificações que não chegam a ser nova funcionalidade, por exemplo, alterar a cor de algo +- **Improvement:** Melhoria significativa em alguma funcionalidade já existente, por exemplo, melhorar uma validação de um formulário +- **Quality:** Tarefas que envolvem a qualidade do código, normalmente algumra refatoração +- **Discovery:** Dificilmente envolvem código, mas sim, levantamento de informações sobre alguma biblioteca e/ou abordagem técnica a ser utilizada, por exemplo, uso da autenticação com GovBr +- **Docs:** Tarefas que envolvem criação e/ou melhoria exclusivamente da documentação, como a criação deste fluxo + +> Para abrir uma nova issue, [clique aqui](https://github.com/secultce/mapacultural/issues/new/choose) + +--- + +## Branches + +> O branch principal (produção), é o `main`, ele não é atualizado constantemente, e toda e qualquer alteração deve ser feita através de pull requests vindos diretamente da branch `develop` + + +```mermaid +--- +title: Exemplo do fluxo de vida dos branches +--- +gitGraph + commit + commit + branch homolog + commit + commit + branch develop + commit + checkout develop + branch fix/any-bug + commit + checkout develop + commit + merge fix/any-bug + checkout homolog + merge develop + commit + checkout main + merge homolog +``` +> Para abrir um novo Pull Request, [leia aqui](./CREATE-PULL-REQUESTS.md) + + +## Sprints + +### Tarefas (Issues/Tasks) + +Internamente a equipe se autogerencia seguindo as boas práticas da metodologia SCRUM e do desenvolvimento ágil, escolhendo, de acordo com suas habilidades e disponibilidades aquelas issues que fazem sentido e são possíveis de serem implementadas: + +```mermaid +graph TD; + Idea-->ProductBacklog + ProductBacklog-->SprintBacklog; + SprintBacklog-->ToDo; + ToDo-->InProgress; + InProgress-->Blocked; + InProgress-->Review; + Review-->Test; + Review-->InProgress; + Test-->Done; + Test-->InProgress; + Blocked-->ProductBacklog; + Blocked-->Closed; +``` + +- **Idea:** é um status de uma issue ainda em criação e/ou rascunho, ao ser finalizada a mesma é automaticamente entendida como "Product Backlog" +- **Product Backlog:** Basicamente significa que isso deve ser entregue, não sabe-se certo quando, mas precisa ser entregue em algum momento +- **Sprint Backlog:** Deve ser entregue nas duas próximas semanas (ou na semana corrente) +- **ToDo:** Já possui alguém (auto) definido para essa task, e essa pessoa já está atrás das informações necessárias para a mesma +- **InProgress:** O trabalho começou a ser de fato realizado (codificando) +- **Review:** O código está pronto para ser revisado por outras pessoas do time +- **Test:** O código já foi revisado e precisa ser testado no ambiente de homologação +- **Done** O código já foi revisado e precisa ser testado no ambiente de homologação +- **Closes:** O código já foi revisado e precisa ser testado no ambiente de homologação + +### Prioridades (Priority) + + + + + + + + + + + + + + + + + + + + + +
PrioridadeDescrição
Very HighTarefa de prioridade máxima, provavelmente um bug
HighTarefa de prioridade alta, provavelmente algo que não esteja funcionando corretamente
MediumTarefa normal
LowTarefa um pouco importante
Very LowTarefa que não é nem um pouco importante
+ +### Peso (Weight) + + + + + + + + + + + + + + + + + + + +
PesoDescrição
1Tarefa muito simples
2Tarefa simples
3Tarefa mediana
5Tarefa muito complexa
+ +seguindo a sequência fibonacci, se uma task tiver tamanho 8 (oito), significa que precisa ser quebrada em duas ou mais \ No newline at end of file diff --git a/public/docs/v2/components/paths/authentication/login.yaml b/public/docs/v2/components/paths/authentication/login.yaml new file mode 100644 index 0000000000..d50a92bba6 --- /dev/null +++ b/public/docs/v2/components/paths/authentication/login.yaml @@ -0,0 +1,31 @@ +post: + tags: + - Autenticação + summary: Faz o login de um usuário. + description: O login permite a geração de um token de acesso para acesso a API. + requestBody: + content: + application/json: + schema: + type: object + properties: + email: + type: string + example: chiquim@email.com + description: O email do usuário + password: + type: string + example: 12345678 + description: A senha do usuário + responses: + '200': + description: O token de acesso para este usuário. + content: + application/json: + schema: + type: object + properties: + token: + type: string + example: jbca87tg2hr928yf6gy2db8yug6q + description: O token de acesso diff --git a/public/docs/v2/components/paths/opportunity/delete.yaml b/public/docs/v2/components/paths/opportunity/delete.yaml index c80aecd995..bc32498d4e 100644 --- a/public/docs/v2/components/paths/opportunity/delete.yaml +++ b/public/docs/v2/components/paths/opportunity/delete.yaml @@ -1,18 +1,18 @@ -- tags: - - Oportunidades - summary: Exclui uma oportunidade existente - description: Remove uma oportunidade do sistema com base no ID fornecido. - parameters: - - in: path - name: id - required: true - schema: - type: integer - description: ID da oportunidade a ser excluída - responses: - '204': - description: Oportunidade excluída com sucesso - '404': - description: Oportunidade não encontrada - '400': - description: Solicitação inválida (ID incorreto ou faltando) +tags: + - Oportunidades +summary: Exclui uma oportunidade existente +description: Remove uma oportunidade do sistema com base no ID fornecido. +parameters: + - in: path + name: id + required: true + schema: + type: integer + description: ID da oportunidade a ser excluída +responses: + '204': + description: Oportunidade excluída com sucesso + '404': + description: Oportunidade não encontrada + '400': + description: Solicitação inválida (ID incorreto ou faltando) diff --git a/public/docs/v2/components/paths/opportunity/get-one.yaml b/public/docs/v2/components/paths/opportunity/get-one.yaml index bc64cc9116..3db7b7491b 100644 --- a/public/docs/v2/components/paths/opportunity/get-one.yaml +++ b/public/docs/v2/components/paths/opportunity/get-one.yaml @@ -1,14 +1,13 @@ -get: - tags: - - Oportunidades - summary: Recupera uma única oportunidade - description: Recupera uma única oportunidade - parameters: - - $ref: '../../parameters/path/id.yaml' - responses: - '200': - description: Success - content: - application/json: - schema: - $ref: '../../schemas/opportunity.yaml' +tags: + - Oportunidades +summary: Recupera uma única oportunidade +description: Recupera uma única oportunidade +parameters: + - $ref: '../../parameters/path/id.yaml' +responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '../../schemas/opportunity.yaml' diff --git a/public/docs/v2/components/paths/term/create.yaml b/public/docs/v2/components/paths/term/create.yaml new file mode 100644 index 0000000000..771238585d --- /dev/null +++ b/public/docs/v2/components/paths/term/create.yaml @@ -0,0 +1,16 @@ +tags: + - Termos +summary: Cria um termo +description: Cria um novo termo a partir dos dados fornecidos +requestBody: + content: + application/json: + schema: + $ref: '../../requestBodies/term/post.yaml' +responses: + '201': + description: Termo criado com sucesso. + content: + application/json: + schema: + $ref: '../../responses/term/created.yaml' diff --git a/public/docs/v2/components/paths/term/delete.yaml b/public/docs/v2/components/paths/term/delete.yaml new file mode 100644 index 0000000000..7fb05b0f2c --- /dev/null +++ b/public/docs/v2/components/paths/term/delete.yaml @@ -0,0 +1,11 @@ +tags: + - Termos +summary: Apaga um termo +description: Apaga um termo existente +parameters: + - $ref: '../../parameters/path/id.yaml' +responses: + '204': + description: O termo foi excluído com sucesso. + '404': + $ref: '../../responses/error/404.yaml' \ No newline at end of file diff --git a/public/docs/v2/components/paths/term/group-get-post.yaml b/public/docs/v2/components/paths/term/group-get-post.yaml index d16afbb028..69379b72d1 100644 --- a/public/docs/v2/components/paths/term/group-get-post.yaml +++ b/public/docs/v2/components/paths/term/group-get-post.yaml @@ -1,2 +1,5 @@ get: $ref: './get-list.yaml' + +post: + $ref: './create.yaml' diff --git a/public/docs/v2/components/paths/term/group-param-id.yaml b/public/docs/v2/components/paths/term/group-param-id.yaml index 0b08f7dec2..4f90fbfee3 100644 --- a/public/docs/v2/components/paths/term/group-param-id.yaml +++ b/public/docs/v2/components/paths/term/group-param-id.yaml @@ -1,2 +1,8 @@ get: $ref: './get-one.yaml' + +patch: + $ref: './update.yaml' + +delete: + $ref: './delete.yaml' diff --git a/public/docs/v2/components/paths/term/update.yaml b/public/docs/v2/components/paths/term/update.yaml new file mode 100644 index 0000000000..833a683fbe --- /dev/null +++ b/public/docs/v2/components/paths/term/update.yaml @@ -0,0 +1,23 @@ +tags: + - Termos +summary: Atualiza um termo +description: Atualiza um termo no sistema com as informações fornecidas. +parameters: + - in: path + name: id + required: true + description: ID do termo a ser atualizado + example: 1 +requestBody: + required: true + content: + application/json: + schema: + $ref: '../../requestBodies/term/post.yaml' +responses: + '201': + description: Termo atualizado com sucesso + content: + application/json: + schema: + $ref: '../../responses/term/created.yaml' diff --git a/public/docs/v2/components/requestBodies/term/post.yaml b/public/docs/v2/components/requestBodies/term/post.yaml new file mode 100644 index 0000000000..943f857a4a --- /dev/null +++ b/public/docs/v2/components/requestBodies/term/post.yaml @@ -0,0 +1,14 @@ +type: object +properties: + taxonomy: + type: string + example: "area" + description: Tipo de termo + term: + type: string + example: "Artes Circenses" + description: Nome do termo + description: + type: string + example: "Artes circenses são manifestações artísticas que combinam elementos de circo, teatro, dança e música." + description: Texto descritivo do termo diff --git a/public/docs/v2/components/responses/term/created.yaml b/public/docs/v2/components/responses/term/created.yaml new file mode 100644 index 0000000000..1aaaab67b4 --- /dev/null +++ b/public/docs/v2/components/responses/term/created.yaml @@ -0,0 +1,38 @@ +type: object +properties: + "@entityType": + type: string + example: "term" + description: Tipo de entidade + id: + type: integer + example: 1 + description: Identificador único do termo + taxonomy: + type: string + example: "area" + description: Tipo de termo + term: + type: string + example: "Artes Circenses" + description: Nome do termo + description: + type: string + example: "Artes circenses são manifestações artísticas que combinam elementos de circo, teatro, dança e música." + description: Texto descritivo do termo + controllerId: + type: string + example: "term" + description: Identificador do controlador + deleteUrl: + type: string + example: "http://localhost/term/apaga/1/" + description: URL para apagar o termo + editUrl: + type: string + example: "http://localhost/term/edita/1/" + description: URL para editar o termo + singleUrl: + type: string + example: "http://localhost/term/acesso/1/" + description: URL para acessar o termo diff --git a/public/docs/v2/components/schemas/user.yaml b/public/docs/v2/components/schemas/user.yaml new file mode 100644 index 0000000000..d22ee45aa2 --- /dev/null +++ b/public/docs/v2/components/schemas/user.yaml @@ -0,0 +1,14 @@ +type: object +properties: + id: + type: integer + example: 1819 + description: Um id numérico que representa o usuário + name: + type: string + example: Chiquim da Silva + description: O nome do usuário + email: + type: string + example: chiquim@email.com + description: O email do usuário diff --git a/public/docs/v2/openapi.yaml b/public/docs/v2/openapi.yaml index 43db0b2b06..af3d4b4c56 100644 --- a/public/docs/v2/openapi.yaml +++ b/public/docs/v2/openapi.yaml @@ -20,6 +20,8 @@ externalDocs: servers: - url: /api/v2 tags: + - name: Autenticação + description: Rotas relacionadas aos agentes - name: Agentes description: Rotas relacionadas aos agentes - name: Espaços @@ -49,6 +51,8 @@ paths: $ref: './components/paths/event/group-param-id.yaml' /events/types: $ref: './components/paths/event/get-type-list.yaml' + /auth: + $ref: './components/paths/authentication/login.yaml' /opportunities: $ref: './components/paths/opportunity/group-get-post.yaml' /opportunities/{id}: @@ -89,3 +93,5 @@ components: $ref: './components/schemas/space.yaml' Term: $ref: './components/schemas/term.yaml' + User: + $ref: './components/schemas/user.yaml' diff --git a/src/core/Entities/Term.php b/src/core/Entities/Term.php index 1b7003c1c5..246435d363 100644 --- a/src/core/Entities/Term.php +++ b/src/core/Entities/Term.php @@ -83,4 +83,39 @@ public function postRemove($args = null){ parent::postRemove($args); } public function preUpdate($args = null){ parent::preUpdate($args); } /** @ORM\PostUpdate */ public function postUpdate($args = null){ parent::postUpdate($args); } + + public function getId(): int + { + return $this->id; + } + + public function getTaxonomy(): string + { + return $this->taxonomy; + } + + public function setTaxonomy(string $taxonomy): void + { + $this->taxonomy = $taxonomy; + } + + public function getTerm(): string + { + return $this->term; + } + + public function setTerm(string $term): void + { + $this->term = $term; + } + + public function getDescription(): string + { + return $this->description; + } + + public function setDescription(string $description): void + { + $this->description = $description; + } } diff --git a/src/core/Entities/User.php b/src/core/Entities/User.php index 0ffeef8509..6abf6e6bd5 100644 --- a/src/core/Entities/User.php +++ b/src/core/Entities/User.php @@ -6,6 +6,7 @@ use MapasCulturais\API; use MapasCulturais\ApiQuery; use MapasCulturais\App; +use MapasCulturais\GuestUser; use MapasCulturais\i; use MapasCulturais\Exceptions\PermissionDenied; use MapasCulturais\Exceptions\BadRequest; @@ -53,6 +54,11 @@ class User extends \MapasCulturais\Entity implements \MapasCulturais\UserInterfa */ protected $authProvider; + /** + * @ORM\Column(name="auth_token", nullable=true) + */ + protected string $authToken; + /** * @var string * @@ -384,6 +390,16 @@ public function setAuthUid(string $authUid): void $this->authUid = $authUid; } + public function setAuthToken(string $authToken): void + { + $this->authToken = $authToken; + } + + public function getAuthToken(): string + { + return $this->authToken; + } + public function getRegistrationsByStatus($status = 0){ $app = App::i(); @@ -972,7 +988,7 @@ public function transferEntitiesTo(Agent $target_agent, $flush = false){ } } - protected function canUserDeleteAccount(User $user){ + protected function canUserDeleteAccount(User|GuestUser $user){ return $user->is('admin') || $user->equals($this); } diff --git a/src/core/Entity.php b/src/core/Entity.php index 813036b152..4548ea3eb0 100644 --- a/src/core/Entity.php +++ b/src/core/Entity.php @@ -1,6 +1,7 @@ canUser($action)) throw new Exceptions\PermissionDenied(App::i()->user, $this, $action); } @@ -906,7 +911,9 @@ public function save($flush = false){ * @param boolean $flush Flushes to the database */ public function delete($flush = false){ - $this->checkPermission('remove'); + if (false === Environment::isLocal()) { + $this->checkPermission('remove'); + } App::i()->em->remove($this); if($flush) @@ -1235,6 +1242,10 @@ public function postPersist($args = null){ * @hook **entity({$entity_class}).remove:before** */ public function preRemove($args = null){ + if (true === Environment::isLocal()) { + return; + } + $app = App::i(); $hook_prefix = $this->getHookPrefix(); diff --git a/src/cypress/.eslintrc.js b/src/cypress/.eslintrc.js index 540c4da613..a77959ec6f 100644 --- a/src/cypress/.eslintrc.js +++ b/src/cypress/.eslintrc.js @@ -1,6 +1,6 @@ module.exports = { extends: [ - 'semistandard', + "semistandard", "plugin:cypress/recommended" ], rules: { diff --git a/src/cypress/commands/login.js b/src/cypress/commands/login.js index 5174597cf8..c92b395782 100644 --- a/src/cypress/commands/login.js +++ b/src/cypress/commands/login.js @@ -1,6 +1,4 @@ -const { confirmRecaptcha } = require("./recaptcha"); - -function login () { +function login() { cy.visit("/autenticacao/"); cy.get("input[id='email']").type("Admin@local"); cy.get("input[id='password']").type("mapas123"); @@ -10,14 +8,4 @@ function login () { cy.url().should("include", "/painel"); } -function loginWith (username, password) { - cy.get("input[id='email']").type(username); - if (password) { - cy.get("input[id='password']").type(password); - } - confirmRecaptcha(); - cy.wait(1000); - cy.get("button[type='submit']").click(); -} - -module.exports = { login, loginWith }; +module.exports = { login }; diff --git a/src/cypress/commands/searchBar.js b/src/cypress/commands/searchBar.js new file mode 100644 index 0000000000..384c5dcb90 --- /dev/null +++ b/src/cypress/commands/searchBar.js @@ -0,0 +1,15 @@ +function searchBar (searchText, expectedResultsCount, expectedText) { + cy.get(".search-filter__actions--form > .search-filter__actions--form-input").type(searchText); + + if (expectedResultsCount) { + cy.wait(1200); + cy.contains(expectedResultsCount); + } + + if (expectedText) { + cy.wait(1200); + cy.contains(expectedText); + } +} + +module.exports = { searchBar }; diff --git a/src/cypress/cypress.config.js b/src/cypress/cypress.config.js index 97f47c4127..e985e2e584 100644 --- a/src/cypress/cypress.config.js +++ b/src/cypress/cypress.config.js @@ -2,8 +2,9 @@ const { defineConfig } = require("cypress"); module.exports = defineConfig({ e2e: { + baseUrl: 'http://localhost', + chromeWebSecurity: false, setupNodeEvents(on, config) { - // implement node event listeners here }, }, }); diff --git a/src/cypress/cypress/fixtures/example.json b/src/cypress/cypress/fixtures/example.json deleted file mode 100644 index 02e4254378..0000000000 --- a/src/cypress/cypress/fixtures/example.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "name": "Using fixtures to represent data", - "email": "hello@cypress.io", - "body": "Fixtures are a great way to mock data for responses to routes" -} diff --git a/src/cypress/cypress/support/commands.js b/src/cypress/cypress/support/commands.js deleted file mode 100644 index 66ea16ef0e..0000000000 --- a/src/cypress/cypress/support/commands.js +++ /dev/null @@ -1,25 +0,0 @@ -// *********************************************** -// This example commands.js shows you how to -// create various custom commands and overwrite -// existing commands. -// -// For more comprehensive examples of custom -// commands please read more here: -// https://on.cypress.io/custom-commands -// *********************************************** -// -// -// -- This is a parent command -- -// Cypress.Commands.add('login', (email, password) => { ... }) -// -// -// -- This is a child command -- -// Cypress.Commands.add('drag', { prevSubject: 'element'}, (subject, options) => { ... }) -// -// -// -- This is a dual command -- -// Cypress.Commands.add('dismiss', { prevSubject: 'optional'}, (subject, options) => { ... }) -// -// -// -- This will overwrite an existing command -- -// Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... }) \ No newline at end of file diff --git a/src/cypress/cypress/support/e2e.js b/src/cypress/cypress/support/e2e.js deleted file mode 100644 index 0e7290a13d..0000000000 --- a/src/cypress/cypress/support/e2e.js +++ /dev/null @@ -1,20 +0,0 @@ -// *********************************************************** -// This example support/e2e.js is processed and -// loaded automatically before your test files. -// -// This is a great place to put global configuration and -// behavior that modifies Cypress. -// -// You can change the location of this file or turn off -// automatically serving support files with the -// 'supportFile' configuration option. -// -// You can read more here: -// https://on.cypress.io/configuration -// *********************************************************** - -// Import commands.js using ES2015 syntax: -import './commands' - -// Alternatively you can use CommonJS syntax: -// require('./commands') \ No newline at end of file diff --git a/src/cypress/package-lock.json b/src/cypress/package-lock.json new file mode 100644 index 0000000000..f6c81424bc --- /dev/null +++ b/src/cypress/package-lock.json @@ -0,0 +1,4090 @@ +{ + "name": "mapacultural", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "mapacultural", + "version": "1.0.0", + "license": "ISC", + "dependencies": { + "cypress": "^13.11.0", + "ng-recaptcha": "^13.2.1" + }, + "devDependencies": { + "eslint": "^8.56.0", + "eslint-config-semistandard": "^17.0.0", + "eslint-config-standard": "^17.1.0", + "eslint-plugin-cypress": "^2.15.1", + "eslint-plugin-import": "^2.29.1", + "eslint-plugin-n": "^15.7.0", + "eslint-plugin-promise": "^6.1.1", + "husky": "^9.0.11" + } + }, + "node_modules/@angular/core": { + "version": "17.3.11", + "resolved": "https://registry.npmjs.org/@angular/core/-/core-17.3.11.tgz", + "integrity": "sha512-2wPZwXFei3kVxK2ylIH6CdGebrC4kvooFx7qoX+250OITAEFMODJGdh/e3x0DpFUjlRvQtIFQ+YpQlfC5JnL4g==", + "peer": true, + "dependencies": { + "tslib": "^2.3.0" + }, + "engines": { + "node": "^18.13.0 || >=20.9.0" + }, + "peerDependencies": { + "rxjs": "^6.5.3 || ^7.4.0", + "zone.js": "~0.14.0" + } + }, + "node_modules/@colors/colors": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", + "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==", + "optional": true, + "engines": { + "node": ">=0.1.90" + } + }, + "node_modules/@cypress/request": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@cypress/request/-/request-3.0.1.tgz", + "integrity": "sha512-TWivJlJi8ZDx2wGOw1dbLuHJKUYX7bWySw377nlnGOW3hP9/MUKIsEdXT/YngWxVdgNCHRBmFlBipE+5/2ZZlQ==", + "dependencies": { + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~2.3.2", + "http-signature": "~1.3.6", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "performance-now": "^2.1.0", + "qs": "6.10.4", + "safe-buffer": "^5.1.2", + "tough-cookie": "^4.1.3", + "tunnel-agent": "^0.6.0", + "uuid": "^8.3.2" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/@cypress/xvfb": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@cypress/xvfb/-/xvfb-1.2.4.tgz", + "integrity": "sha512-skbBzPggOVYCbnGgV+0dmBdW/s77ZkAOXIC1knS8NagwDjBrNC1LuXtQJeiN6l+m7lzmHtaoUw/ctJKdqkG57Q==", + "dependencies": { + "debug": "^3.1.0", + "lodash.once": "^4.1.1" + } + }, + "node_modules/@cypress/xvfb/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", + "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "dev": true, + "dependencies": { + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.1.tgz", + "integrity": "sha512-Zm2NGpWELsQAD1xsJzGQpYfvICSsFkEpU0jxBjfdC6uNEWXcHnfs9hScFWtXVDVl+rBQJGrl4g1vcKIejpH9dA==", + "dev": true, + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", + "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", + "dev": true, + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.6.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/js": { + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.0.tgz", + "integrity": "sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/@humanwhocodes/config-array": { + "version": "0.11.14", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", + "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==", + "deprecated": "Use @eslint/config-array instead", + "dev": true, + "dependencies": { + "@humanwhocodes/object-schema": "^2.0.2", + "debug": "^4.3.1", + "minimatch": "^3.0.5" + }, + "engines": { + "node": ">=10.10.0" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/object-schema": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", + "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", + "deprecated": "Use @eslint/object-schema instead", + "dev": true + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@types/grecaptcha": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/@types/grecaptcha/-/grecaptcha-3.0.9.tgz", + "integrity": "sha512-fFxMtjAvXXMYTzDFK5NpcVB7WHnrHVLl00QzEGpuFxSAC789io6M+vjcn+g5FTEamIJtJr/IHkCDsqvJxeWDyw==" + }, + "node_modules/@types/json5": { + "version": "0.0.29", + "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", + "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", + "dev": true + }, + "node_modules/@types/node": { + "version": "20.14.2", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.2.tgz", + "integrity": "sha512-xyu6WAMVwv6AKFLB+e/7ySZVr/0zLCzOa7rSpq6jNwpqOrUbcACDWC+53d4n2QHOnDou0fbIsg8wZu/sxrnI4Q==", + "optional": true, + "dependencies": { + "undici-types": "~5.26.4" + } + }, + "node_modules/@types/sinonjs__fake-timers": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-8.1.1.tgz", + "integrity": "sha512-0kSuKjAS0TrGLJ0M/+8MaFkGsQhZpB6pxOmvS3K8FYI72K//YmdfoW9X2qPsAKh1mkwxGD5zib9s1FIFed6E8g==" + }, + "node_modules/@types/sizzle": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/@types/sizzle/-/sizzle-2.3.8.tgz", + "integrity": "sha512-0vWLNK2D5MT9dg0iOo8GlKguPAU02QjmZitPEsXRuJXU/OGIOt9vT9Fc26wtYuavLxtO45v9PGleoL9Z0k1LHg==" + }, + "node_modules/@types/yauzl": { + "version": "2.10.3", + "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.3.tgz", + "integrity": "sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==", + "optional": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@ungap/structured-clone": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", + "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", + "dev": true + }, + "node_modules/acorn": { + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.0.tgz", + "integrity": "sha512-RTvkC4w+KNXrM39/lWCUaG0IbRkWdCv7W/IOW9oU6SawyxulvkQy5HQPVTKxEjczcUvapcrw3cFx/60VN/NRNw==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/aggregate-error": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", + "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", + "dependencies": { + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ansi-colors": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", + "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", + "engines": { + "node": ">=6" + } + }, + "node_modules/ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "dependencies": { + "type-fest": "^0.21.3" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-escapes/node_modules/type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/arch": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/arch/-/arch-2.2.0.tgz", + "integrity": "sha512-Of/R0wqp83cgHozfIYLbBMnej79U/SVGOOyuB3VVFv1NRM/PSFMK12x9KVtiYzJqmnU5WR2qp0Z5rHb7sWGnFQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "node_modules/array-buffer-byte-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz", + "integrity": "sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.5", + "is-array-buffer": "^3.0.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array-includes": { + "version": "3.1.8", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.8.tgz", + "integrity": "sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.4", + "is-string": "^1.0.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.findlastindex": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.5.tgz", + "integrity": "sha512-zfETvRFA8o7EiNn++N5f/kaCw221hrpGsDmcpndVupkPzEc1Wuf3VgC0qby1BbHs7f5DVYjgtEU2LLh5bqeGfQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.flat": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz", + "integrity": "sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "es-shim-unscopables": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.flatmap": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.2.tgz", + "integrity": "sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "es-shim-unscopables": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/arraybuffer.prototype.slice": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.3.tgz", + "integrity": "sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==", + "dev": true, + "dependencies": { + "array-buffer-byte-length": "^1.0.1", + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", + "es-abstract": "^1.22.3", + "es-errors": "^1.2.1", + "get-intrinsic": "^1.2.3", + "is-array-buffer": "^3.0.4", + "is-shared-array-buffer": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/asn1": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz", + "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==", + "dependencies": { + "safer-buffer": "~2.1.0" + } + }, + "node_modules/assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==", + "engines": { + "node": ">=0.8" + } + }, + "node_modules/astral-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", + "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/async": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.5.tgz", + "integrity": "sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg==" + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + }, + "node_modules/at-least-node": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", + "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/available-typed-arrays": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", + "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", + "dev": true, + "dependencies": { + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==", + "engines": { + "node": "*" + } + }, + "node_modules/aws4": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.13.0.tgz", + "integrity": "sha512-3AungXC4I8kKsS9PuS4JH2nc+0bVY/mjgrephHTIi8fpEeGsTHBUJeosp0Wc1myYMElmD0B3Oc4XL/HVJ4PV2g==" + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/bcrypt-pbkdf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==", + "dependencies": { + "tweetnacl": "^0.14.3" + } + }, + "node_modules/blob-util": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/blob-util/-/blob-util-2.0.2.tgz", + "integrity": "sha512-T7JQa+zsXXEa6/8ZhHcQEW1UFfVM49Ts65uBkFL6fz2QmrElqmbajIDJvuA0tEhRe5eIjpV9ZF+0RfZR9voJFQ==" + }, + "node_modules/bluebird": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", + "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==" + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "node_modules/buffer-crc32": { + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", + "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", + "engines": { + "node": "*" + } + }, + "node_modules/builtins": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/builtins/-/builtins-5.1.0.tgz", + "integrity": "sha512-SW9lzGTLvWTP1AY8xeAMZimqDrIaSdLQUcVr9DMef51niJ022Ri87SwRRKYm4A6iHfkPaiVUu/Duw2Wc4J7kKg==", + "dev": true, + "dependencies": { + "semver": "^7.0.0" + } + }, + "node_modules/cachedir": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/cachedir/-/cachedir-2.4.0.tgz", + "integrity": "sha512-9EtFOZR8g22CL7BWjJ9BUx1+A/djkofnyW3aOXZORNW2kxoUpx2h+uN2cOqwPmFhnpVmxg+KW2OjOSgChTEvsQ==", + "engines": { + "node": ">=6" + } + }, + "node_modules/call-bind": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", + "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==" + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/chalk/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/check-more-types": { + "version": "2.24.0", + "resolved": "https://registry.npmjs.org/check-more-types/-/check-more-types-2.24.0.tgz", + "integrity": "sha512-Pj779qHxV2tuapviy1bSZNEL1maXr13bPYpsvSDB68HlYcYuhlDrmGd63i0JHMCLKzc7rUSNIrpdJlhVlNwrxA==", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/ci-info": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "engines": { + "node": ">=8" + } + }, + "node_modules/clean-stack": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", + "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", + "engines": { + "node": ">=6" + } + }, + "node_modules/cli-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", + "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", + "dependencies": { + "restore-cursor": "^3.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cli-table3": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.5.tgz", + "integrity": "sha512-+W/5efTR7y5HRD7gACw9yQjqMVvEMLBHmboM/kPWam+H+Hmyrgjh6YncVKK122YZkXrLudzTuAukUw9FnMf7IQ==", + "dependencies": { + "string-width": "^4.2.0" + }, + "engines": { + "node": "10.* || >= 12.*" + }, + "optionalDependencies": { + "@colors/colors": "1.5.0" + } + }, + "node_modules/cli-truncate": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-2.1.0.tgz", + "integrity": "sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg==", + "dependencies": { + "slice-ansi": "^3.0.0", + "string-width": "^4.2.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/colorette": { + "version": "2.0.20", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", + "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==" + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/commander": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz", + "integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==", + "engines": { + "node": ">= 6" + } + }, + "node_modules/common-tags": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/common-tags/-/common-tags-1.8.2.tgz", + "integrity": "sha512-gk/Z852D2Wtb//0I+kRFNKKE9dIIVirjoqPoA1wJU+XePVXZfGeBpk45+A1rKO4Q43prqWBNY/MiIeRLbPWUaA==", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true + }, + "node_modules/core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==" + }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/cypress": { + "version": "13.11.0", + "resolved": "https://registry.npmjs.org/cypress/-/cypress-13.11.0.tgz", + "integrity": "sha512-NXXogbAxVlVje4XHX+Cx5eMFZv4Dho/2rIcdBHg9CNPFUGZdM4cRdgIgM7USmNYsC12XY0bZENEQ+KBk72fl+A==", + "hasInstallScript": true, + "dependencies": { + "@cypress/request": "^3.0.0", + "@cypress/xvfb": "^1.2.4", + "@types/sinonjs__fake-timers": "8.1.1", + "@types/sizzle": "^2.3.2", + "arch": "^2.2.0", + "blob-util": "^2.0.2", + "bluebird": "^3.7.2", + "buffer": "^5.7.1", + "cachedir": "^2.3.0", + "chalk": "^4.1.0", + "check-more-types": "^2.24.0", + "cli-cursor": "^3.1.0", + "cli-table3": "~0.6.1", + "commander": "^6.2.1", + "common-tags": "^1.8.0", + "dayjs": "^1.10.4", + "debug": "^4.3.4", + "enquirer": "^2.3.6", + "eventemitter2": "6.4.7", + "execa": "4.1.0", + "executable": "^4.1.1", + "extract-zip": "2.0.1", + "figures": "^3.2.0", + "fs-extra": "^9.1.0", + "getos": "^3.2.1", + "is-ci": "^3.0.1", + "is-installed-globally": "~0.4.0", + "lazy-ass": "^1.6.0", + "listr2": "^3.8.3", + "lodash": "^4.17.21", + "log-symbols": "^4.0.0", + "minimist": "^1.2.8", + "ospath": "^1.2.2", + "pretty-bytes": "^5.6.0", + "process": "^0.11.10", + "proxy-from-env": "1.0.0", + "request-progress": "^3.0.0", + "semver": "^7.5.3", + "supports-color": "^8.1.1", + "tmp": "~0.2.1", + "untildify": "^4.0.0", + "yauzl": "^2.10.0" + }, + "bin": { + "cypress": "bin/cypress" + }, + "engines": { + "node": "^16.0.0 || ^18.0.0 || >=20.0.0" + } + }, + "node_modules/dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==", + "dependencies": { + "assert-plus": "^1.0.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/data-view-buffer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.1.tgz", + "integrity": "sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/data-view-byte-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.1.tgz", + "integrity": "sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/data-view-byte-offset": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.0.tgz", + "integrity": "sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/dayjs": { + "version": "1.11.11", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.11.tgz", + "integrity": "sha512-okzr3f11N6WuqYtZSvm+F776mB41wRZMhKP+hc34YdW+KmtYYK9iqvHSwo2k9FEH3fhGXvOPV6yz2IcSrfRUDg==" + }, + "node_modules/debug": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", + "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true + }, + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/define-properties": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", + "dev": true, + "dependencies": { + "define-data-property": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/ecc-jsbn": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", + "integrity": "sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==", + "dependencies": { + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" + } + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "node_modules/end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/enquirer": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.4.1.tgz", + "integrity": "sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ==", + "dependencies": { + "ansi-colors": "^4.1.1", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/es-abstract": { + "version": "1.23.3", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.3.tgz", + "integrity": "sha512-e+HfNH61Bj1X9/jLc5v1owaLYuHdeHHSQlkhCBiTK8rBvKaULl/beGMxwrMXjpYrv4pz22BlY570vVePA2ho4A==", + "dev": true, + "dependencies": { + "array-buffer-byte-length": "^1.0.1", + "arraybuffer.prototype.slice": "^1.0.3", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", + "data-view-buffer": "^1.0.1", + "data-view-byte-length": "^1.0.1", + "data-view-byte-offset": "^1.0.0", + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-set-tostringtag": "^2.0.3", + "es-to-primitive": "^1.2.1", + "function.prototype.name": "^1.1.6", + "get-intrinsic": "^1.2.4", + "get-symbol-description": "^1.0.2", + "globalthis": "^1.0.3", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.0.3", + "has-symbols": "^1.0.3", + "hasown": "^2.0.2", + "internal-slot": "^1.0.7", + "is-array-buffer": "^3.0.4", + "is-callable": "^1.2.7", + "is-data-view": "^1.0.1", + "is-negative-zero": "^2.0.3", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.3", + "is-string": "^1.0.7", + "is-typed-array": "^1.1.13", + "is-weakref": "^1.0.2", + "object-inspect": "^1.13.1", + "object-keys": "^1.1.1", + "object.assign": "^4.1.5", + "regexp.prototype.flags": "^1.5.2", + "safe-array-concat": "^1.1.2", + "safe-regex-test": "^1.0.3", + "string.prototype.trim": "^1.2.9", + "string.prototype.trimend": "^1.0.8", + "string.prototype.trimstart": "^1.0.8", + "typed-array-buffer": "^1.0.2", + "typed-array-byte-length": "^1.0.1", + "typed-array-byte-offset": "^1.0.2", + "typed-array-length": "^1.0.6", + "unbox-primitive": "^1.0.2", + "which-typed-array": "^1.1.15" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", + "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", + "dependencies": { + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.0.0.tgz", + "integrity": "sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==", + "dev": true, + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.3.tgz", + "integrity": "sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.2.4", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.1" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-shim-unscopables": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.2.tgz", + "integrity": "sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==", + "dev": true, + "dependencies": { + "hasown": "^2.0.0" + } + }, + "node_modules/es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dev": true, + "dependencies": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint": { + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz", + "integrity": "sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/eslintrc": "^2.1.4", + "@eslint/js": "8.57.0", + "@humanwhocodes/config-array": "^0.11.14", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "@ungap/structured-clone": "^1.2.0", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.2.2", + "eslint-visitor-keys": "^3.4.3", + "espree": "^9.6.1", + "esquery": "^1.4.2", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "graphemer": "^1.4.0", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3", + "strip-ansi": "^6.0.1", + "text-table": "^0.2.0" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-config-semistandard": { + "version": "17.0.0", + "resolved": "https://registry.npmjs.org/eslint-config-semistandard/-/eslint-config-semistandard-17.0.0.tgz", + "integrity": "sha512-tLi0JYmfiiJgtmRhoES55tENatR7y/5aXOh6cBeW+qjzl1+WwyV0arDqR65XN3/xrPZt+/1EG+xNLknV/0jWsQ==", + "dev": true, + "peerDependencies": { + "eslint": "^8.13.0", + "eslint-config-standard": "^17.0.0", + "eslint-plugin-import": "^2.26.0", + "eslint-plugin-n": "^15.0.0", + "eslint-plugin-promise": "^6.0.0" + } + }, + "node_modules/eslint-config-standard": { + "version": "17.1.0", + "resolved": "https://registry.npmjs.org/eslint-config-standard/-/eslint-config-standard-17.1.0.tgz", + "integrity": "sha512-IwHwmaBNtDK4zDHQukFDW5u/aTb8+meQWZvNFWkiGmbWjD6bqyuSSBxxXKkCftCUzc1zwCH2m/baCNDLGmuO5Q==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "eslint": "^8.0.1", + "eslint-plugin-import": "^2.25.2", + "eslint-plugin-n": "^15.0.0 || ^16.0.0 ", + "eslint-plugin-promise": "^6.0.0" + } + }, + "node_modules/eslint-import-resolver-node": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz", + "integrity": "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==", + "dev": true, + "dependencies": { + "debug": "^3.2.7", + "is-core-module": "^2.13.0", + "resolve": "^1.22.4" + } + }, + "node_modules/eslint-import-resolver-node/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-module-utils": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.8.1.tgz", + "integrity": "sha512-rXDXR3h7cs7dy9RNpUlQf80nX31XWJEyGq1tRMo+6GsO5VmTe4UTwtmonAD4ZkAsrfMVDA2wlGJ3790Ys+D49Q==", + "dev": true, + "dependencies": { + "debug": "^3.2.7" + }, + "engines": { + "node": ">=4" + }, + "peerDependenciesMeta": { + "eslint": { + "optional": true + } + } + }, + "node_modules/eslint-module-utils/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-plugin-cypress": { + "version": "2.15.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-cypress/-/eslint-plugin-cypress-2.15.2.tgz", + "integrity": "sha512-CtcFEQTDKyftpI22FVGpx8bkpKyYXBlNge6zSo0pl5/qJvBAnzaD76Vu2AsP16d6mTj478Ldn2mhgrWV+Xr0vQ==", + "dev": true, + "dependencies": { + "globals": "^13.20.0" + }, + "peerDependencies": { + "eslint": ">= 3.2.1" + } + }, + "node_modules/eslint-plugin-es": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-es/-/eslint-plugin-es-4.1.0.tgz", + "integrity": "sha512-GILhQTnjYE2WorX5Jyi5i4dz5ALWxBIdQECVQavL6s7cI76IZTDWleTHkxz/QT3kvcs2QlGHvKLYsSlPOlPXnQ==", + "dev": true, + "dependencies": { + "eslint-utils": "^2.0.0", + "regexpp": "^3.0.0" + }, + "engines": { + "node": ">=8.10.0" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + }, + "peerDependencies": { + "eslint": ">=4.19.1" + } + }, + "node_modules/eslint-plugin-es/node_modules/eslint-utils": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", + "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", + "dev": true, + "dependencies": { + "eslint-visitor-keys": "^1.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + } + }, + "node_modules/eslint-plugin-es/node_modules/eslint-visitor-keys": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", + "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/eslint-plugin-import": { + "version": "2.29.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.29.1.tgz", + "integrity": "sha512-BbPC0cuExzhiMo4Ff1BTVwHpjjv28C5R+btTOGaCRC7UEz801up0JadwkeSk5Ued6TG34uaczuVuH6qyy5YUxw==", + "dev": true, + "dependencies": { + "array-includes": "^3.1.7", + "array.prototype.findlastindex": "^1.2.3", + "array.prototype.flat": "^1.3.2", + "array.prototype.flatmap": "^1.3.2", + "debug": "^3.2.7", + "doctrine": "^2.1.0", + "eslint-import-resolver-node": "^0.3.9", + "eslint-module-utils": "^2.8.0", + "hasown": "^2.0.0", + "is-core-module": "^2.13.1", + "is-glob": "^4.0.3", + "minimatch": "^3.1.2", + "object.fromentries": "^2.0.7", + "object.groupby": "^1.0.1", + "object.values": "^1.1.7", + "semver": "^6.3.1", + "tsconfig-paths": "^3.15.0" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8" + } + }, + "node_modules/eslint-plugin-import/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-plugin-import/node_modules/doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dev": true, + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/eslint-plugin-import/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/eslint-plugin-n": { + "version": "15.7.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-n/-/eslint-plugin-n-15.7.0.tgz", + "integrity": "sha512-jDex9s7D/Qial8AGVIHq4W7NswpUD5DPDL2RH8Lzd9EloWUuvUkHfv4FRLMipH5q2UtyurorBkPeNi1wVWNh3Q==", + "dev": true, + "dependencies": { + "builtins": "^5.0.1", + "eslint-plugin-es": "^4.1.0", + "eslint-utils": "^3.0.0", + "ignore": "^5.1.1", + "is-core-module": "^2.11.0", + "minimatch": "^3.1.2", + "resolve": "^1.22.1", + "semver": "^7.3.8" + }, + "engines": { + "node": ">=12.22.0" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + }, + "peerDependencies": { + "eslint": ">=7.0.0" + } + }, + "node_modules/eslint-plugin-promise": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-6.2.0.tgz", + "integrity": "sha512-QmAqwizauvnKOlifxyDj2ObfULpHQawlg/zQdgEixur9vl0CvZGv/LCJV2rtj3210QCoeGBzVMfMXqGAOr/4fA==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0 || ^9.0.0" + } + }, + "node_modules/eslint-scope": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", + "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-utils": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", + "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", + "dev": true, + "dependencies": { + "eslint-visitor-keys": "^2.0.0" + }, + "engines": { + "node": "^10.0.0 || ^12.0.0 || >= 14.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + }, + "peerDependencies": { + "eslint": ">=5" + } + }, + "node_modules/eslint-utils/node_modules/eslint-visitor-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", + "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/espree": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "dev": true, + "dependencies": { + "acorn": "^8.9.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esquery": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", + "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", + "dev": true, + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/eventemitter2": { + "version": "6.4.7", + "resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-6.4.7.tgz", + "integrity": "sha512-tYUSVOGeQPKt/eC1ABfhHy5Xd96N3oIijJvN3O9+TsC28T5V9yX9oEfEK5faP0EFSNVOG97qtAS68GBrQB2hDg==" + }, + "node_modules/execa": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-4.1.0.tgz", + "integrity": "sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA==", + "dependencies": { + "cross-spawn": "^7.0.0", + "get-stream": "^5.0.0", + "human-signals": "^1.1.1", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.0", + "onetime": "^5.1.0", + "signal-exit": "^3.0.2", + "strip-final-newline": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/executable": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/executable/-/executable-4.1.1.tgz", + "integrity": "sha512-8iA79xD3uAch729dUG8xaaBBFGaEa0wdD2VkYLFHwlqosEj/jT66AzcreRDSgV7ehnNLBW2WR5jIXwGKjVdTLg==", + "dependencies": { + "pify": "^2.2.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" + }, + "node_modules/extract-zip": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz", + "integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==", + "dependencies": { + "debug": "^4.1.1", + "get-stream": "^5.1.0", + "yauzl": "^2.10.0" + }, + "bin": { + "extract-zip": "cli.js" + }, + "engines": { + "node": ">= 10.17.0" + }, + "optionalDependencies": { + "@types/yauzl": "^2.9.1" + } + }, + "node_modules/extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==", + "engines": [ + "node >=0.6.0" + ] + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true + }, + "node_modules/fastq": { + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", + "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", + "dev": true, + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/fd-slicer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", + "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==", + "dependencies": { + "pend": "~1.2.0" + } + }, + "node_modules/figures": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", + "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", + "dependencies": { + "escape-string-regexp": "^1.0.5" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/figures/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, + "dependencies": { + "flat-cache": "^3.0.4" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat-cache": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", + "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", + "dev": true, + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.3", + "rimraf": "^3.0.2" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/flatted": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz", + "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==", + "dev": true + }, + "node_modules/for-each": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", + "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "dev": true, + "dependencies": { + "is-callable": "^1.1.3" + } + }, + "node_modules/forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==", + "engines": { + "node": "*" + } + }, + "node_modules/form-data": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", + "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 0.12" + } + }, + "node_modules/fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "dependencies": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/function.prototype.name": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.6.tgz", + "integrity": "sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "functions-have-names": "^1.2.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-intrinsic": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", + "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/get-symbol-description": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.2.tgz", + "integrity": "sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.5", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/getos": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/getos/-/getos-3.2.1.tgz", + "integrity": "sha512-U56CfOK17OKgTVqozZjUKNdkfEv6jk5WISBJ8SHoagjE6L69zOwl3Z+O8myjY9MEW3i2HPWQBt/LTbCgcC973Q==", + "dependencies": { + "async": "^3.2.0" + } + }, + "node_modules/getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==", + "dependencies": { + "assert-plus": "^1.0.0" + } + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/global-dirs": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-3.0.1.tgz", + "integrity": "sha512-NBcGGFbBA9s1VzD41QXDG+3++t9Mn5t1FpLdhESY6oKY4gYTFpX4wO3sqGUa0Srjtbfj3szX0RnemmrVRUdULA==", + "dependencies": { + "ini": "2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globals": { + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "dev": true, + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globalthis": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", + "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", + "dev": true, + "dependencies": { + "define-properties": "^1.2.1", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "dependencies": { + "get-intrinsic": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" + }, + "node_modules/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true + }, + "node_modules/has-bigints": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", + "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "dependencies": { + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", + "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "dev": true, + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/http-signature": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.3.6.tgz", + "integrity": "sha512-3adrsD6zqo4GsTqtO7FyrejHNv+NgiIfAfv68+jVlFmSr9OGy7zrxONceFRLKvnnZA5jbxQBX1u9PpB6Wi32Gw==", + "dependencies": { + "assert-plus": "^1.0.0", + "jsprim": "^2.0.2", + "sshpk": "^1.14.1" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/human-signals": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-1.1.1.tgz", + "integrity": "sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==", + "engines": { + "node": ">=8.12.0" + } + }, + "node_modules/husky": { + "version": "9.0.11", + "resolved": "https://registry.npmjs.org/husky/-/husky-9.0.11.tgz", + "integrity": "sha512-AB6lFlbwwyIqMdHYhwPe+kjOC3Oc5P3nThEoW/AaO2BX3vJDjWPFxYLxokUZOo6RNX20He3AaT8sESs9NJcmEw==", + "dev": true, + "bin": { + "husky": "bin.mjs" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/typicode" + } + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/ignore": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", + "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "engines": { + "node": ">=8" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "dev": true, + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "node_modules/ini": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ini/-/ini-2.0.0.tgz", + "integrity": "sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA==", + "engines": { + "node": ">=10" + } + }, + "node_modules/internal-slot": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.7.tgz", + "integrity": "sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==", + "dev": true, + "dependencies": { + "es-errors": "^1.3.0", + "hasown": "^2.0.0", + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/is-array-buffer": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.4.tgz", + "integrity": "sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-bigint": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", + "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", + "dev": true, + "dependencies": { + "has-bigints": "^1.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-boolean-object": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", + "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-callable": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-ci": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-3.0.1.tgz", + "integrity": "sha512-ZYvCgrefwqoQ6yTyYUbQu64HsITZ3NfKX1lzaEYdkTDcfKzzCI/wthRRYKkdjHKFVgNiXKAKm65Zo1pk2as/QQ==", + "dependencies": { + "ci-info": "^3.2.0" + }, + "bin": { + "is-ci": "bin.js" + } + }, + "node_modules/is-core-module": { + "version": "2.13.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz", + "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==", + "dev": true, + "dependencies": { + "hasown": "^2.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-data-view": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.1.tgz", + "integrity": "sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w==", + "dev": true, + "dependencies": { + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-date-object": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", + "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-installed-globally": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.4.0.tgz", + "integrity": "sha512-iwGqO3J21aaSkC7jWnHP/difazwS7SFeIqxv6wEtLU8Y5KlzFTjyqcSIT0d8s4+dDhKytsk9PJZ2BkS5eZwQRQ==", + "dependencies": { + "global-dirs": "^3.0.0", + "is-path-inside": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-negative-zero": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", + "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-number-object": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", + "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-regex": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", + "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-shared-array-buffer": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.3.tgz", + "integrity": "sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-string": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", + "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-symbol": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", + "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", + "dev": true, + "dependencies": { + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-typed-array": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.13.tgz", + "integrity": "sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==", + "dev": true, + "dependencies": { + "which-typed-array": "^1.1.14" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==" + }, + "node_modules/is-unicode-supported": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", + "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-weakref": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", + "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" + }, + "node_modules/isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==" + }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==" + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true + }, + "node_modules/json-schema": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", + "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==" + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true + }, + "node_modules/json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==" + }, + "node_modules/json5": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", + "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", + "dev": true, + "dependencies": { + "minimist": "^1.2.0" + }, + "bin": { + "json5": "lib/cli.js" + } + }, + "node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/jsprim": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-2.0.2.tgz", + "integrity": "sha512-gqXddjPqQ6G40VdnI6T6yObEC+pDNvyP95wdQhkWkg7crHH3km5qP1FsOXEkzEQwnz6gz5qGTn1c2Y52wP3OyQ==", + "engines": [ + "node >=0.6.0" + ], + "dependencies": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.4.0", + "verror": "1.10.0" + } + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/lazy-ass": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/lazy-ass/-/lazy-ass-1.6.0.tgz", + "integrity": "sha512-cc8oEVoctTvsFZ/Oje/kGnHbpWHYBe8IAJe4C0QNc3t8uM/0Y8+erSz/7Y1ALuXTEZTMvxXwO6YbX1ey3ujiZw==", + "engines": { + "node": "> 0.8" + } + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/listr2": { + "version": "3.14.0", + "resolved": "https://registry.npmjs.org/listr2/-/listr2-3.14.0.tgz", + "integrity": "sha512-TyWI8G99GX9GjE54cJ+RrNMcIFBfwMPxc3XTFiAYGN4s10hWROGtOg7+O6u6LE3mNkyld7RSLE6nrKBvTfcs3g==", + "dependencies": { + "cli-truncate": "^2.1.0", + "colorette": "^2.0.16", + "log-update": "^4.0.0", + "p-map": "^4.0.0", + "rfdc": "^1.3.0", + "rxjs": "^7.5.1", + "through": "^2.3.8", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "enquirer": ">= 2.3.0 < 3" + }, + "peerDependenciesMeta": { + "enquirer": { + "optional": true + } + } + }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true + }, + "node_modules/lodash.once": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", + "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==" + }, + "node_modules/log-symbols": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", + "dependencies": { + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-update": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/log-update/-/log-update-4.0.0.tgz", + "integrity": "sha512-9fkkDevMefjg0mmzWFBW8YkFP91OrizzkW3diF7CpG+S2EYdy4+TVfGwz1zeF8x7hCx1ovSPTOE9Ngib74qqUg==", + "dependencies": { + "ansi-escapes": "^4.3.0", + "cli-cursor": "^3.1.0", + "slice-ansi": "^4.0.0", + "wrap-ansi": "^6.2.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-update/node_modules/slice-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", + "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", + "dependencies": { + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, + "node_modules/log-update/node_modules/wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==" + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "engines": { + "node": ">=6" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true + }, + "node_modules/ng-recaptcha": { + "version": "13.2.1", + "resolved": "https://registry.npmjs.org/ng-recaptcha/-/ng-recaptcha-13.2.1.tgz", + "integrity": "sha512-aBOoFla9t6AfT9t5paykoXomCDKreBKouB16VUFxSZwn1RCfDsdcaTmSNJKYLFz5j0Cq/V+szY9f3mHLgzRw5Q==", + "dependencies": { + "@types/grecaptcha": "^3.0.7", + "tslib": "^2.2.0" + }, + "peerDependencies": { + "@angular/core": "^17.0.0" + } + }, + "node_modules/npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dependencies": { + "path-key": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/object-inspect": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", + "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.assign": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.5.tgz", + "integrity": "sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", + "has-symbols": "^1.0.3", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.fromentries": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.8.tgz", + "integrity": "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.groupby": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.3.tgz", + "integrity": "sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.values": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.0.tgz", + "integrity": "sha512-yBYjY9QX2hnRmZHAjG/f13MzmBzxzYgQhFrke06TTyKY5zSTEqkOeukBzIdVA3j3ulu8Qa3MbVFShV7T2RmGtQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/optionator": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", + "dev": true, + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/ospath": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/ospath/-/ospath-1.2.2.tgz", + "integrity": "sha512-o6E5qJV5zkAbIDNhGSIlyOhScKXgQrSRMilfph0clDfM0nEnBOlKlH4sWDmG95BW/CvwNz0vmm7dJVtU2KlMiA==" + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-map": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", + "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", + "dependencies": { + "aggregate-error": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true + }, + "node_modules/pend": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", + "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==" + }, + "node_modules/performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==" + }, + "node_modules/pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/possible-typed-array-names": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz", + "integrity": "sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/pretty-bytes": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-5.6.0.tgz", + "integrity": "sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg==", + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==", + "engines": { + "node": ">= 0.6.0" + } + }, + "node_modules/proxy-from-env": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.0.0.tgz", + "integrity": "sha512-F2JHgJQ1iqwnHDcQjVBsq3n/uoaFL+iPW/eAeL7kVxy/2RrWaN4WroKjjvbsoRtv0ftelNyC01bjRhn/bhcf4A==" + }, + "node_modules/psl": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", + "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==" + }, + "node_modules/pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "engines": { + "node": ">=6" + } + }, + "node_modules/qs": { + "version": "6.10.4", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.4.tgz", + "integrity": "sha512-OQiU+C+Ds5qiH91qh/mg0w+8nwQuLjM4F4M/PbmhDOoYehPh+Fb0bDjtR1sOvy7YKxvj28Y/M0PhP5uVX0kB+g==", + "dependencies": { + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/querystringify": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", + "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==" + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/regexp.prototype.flags": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.2.tgz", + "integrity": "sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.6", + "define-properties": "^1.2.1", + "es-errors": "^1.3.0", + "set-function-name": "^2.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/regexpp": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", + "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + } + }, + "node_modules/request-progress": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/request-progress/-/request-progress-3.0.0.tgz", + "integrity": "sha512-MnWzEHHaxHO2iWiQuHrUPBi/1WeBf5PkxQqNyNvLl9VAYSdXkP8tQ3pBSeCPD+yw0v0Aq1zosWLz0BdeXpWwZg==", + "dependencies": { + "throttleit": "^1.0.0" + } + }, + "node_modules/requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==" + }, + "node_modules/resolve": { + "version": "1.22.8", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", + "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", + "dev": true, + "dependencies": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/restore-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", + "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", + "dependencies": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true, + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rfdc": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.4.1.tgz", + "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==" + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/rxjs": { + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", + "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/safe-array-concat": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.2.tgz", + "integrity": "sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "get-intrinsic": "^1.2.4", + "has-symbols": "^1.0.3", + "isarray": "^2.0.5" + }, + "engines": { + "node": ">=0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/safe-regex-test": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.3.tgz", + "integrity": "sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-regex": "^1.1.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "node_modules/semver": { + "version": "7.6.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", + "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/set-function-name": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", + "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", + "dev": true, + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "functions-have-names": "^1.2.3", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "engines": { + "node": ">=8" + } + }, + "node_modules/side-channel": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", + "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", + "dependencies": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4", + "object-inspect": "^1.13.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + }, + "node_modules/slice-ansi": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-3.0.0.tgz", + "integrity": "sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ==", + "dependencies": { + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/sshpk": { + "version": "1.18.0", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.18.0.tgz", + "integrity": "sha512-2p2KJZTSqQ/I3+HX42EpYOa2l3f8Erv8MWKsy2I9uf4wA7yFIkXRffYdsx86y6z4vHtV8u7g+pPlr8/4ouAxsQ==", + "dependencies": { + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" + }, + "bin": { + "sshpk-conv": "bin/sshpk-conv", + "sshpk-sign": "bin/sshpk-sign", + "sshpk-verify": "bin/sshpk-verify" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string.prototype.trim": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.9.tgz", + "integrity": "sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.0", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimend": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.8.tgz", + "integrity": "sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimstart": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz", + "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "engines": { + "node": ">=6" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "dev": true + }, + "node_modules/throttleit": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/throttleit/-/throttleit-1.0.1.tgz", + "integrity": "sha512-vDZpf9Chs9mAdfY046mcPt8fg5QSZr37hEH4TXYBnDF+izxgrbRGUAAaBvIk/fJm9aOFCGFd1EsNg5AZCbnQCQ==", + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==" + }, + "node_modules/tmp": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.3.tgz", + "integrity": "sha512-nZD7m9iCPC5g0pYmcaxogYKggSfLsdxl8of3Q/oIbqCqLLIO9IAF0GWjX1z9NZRHPiXv8Wex4yDCaZsgEw0Y8w==", + "engines": { + "node": ">=14.14" + } + }, + "node_modules/tough-cookie": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.4.tgz", + "integrity": "sha512-Loo5UUvLD9ScZ6jh8beX1T6sO1w2/MpCRpEP7V280GKMVUQ0Jzar2U3UJPsrdbziLEMMhu3Ujnq//rhiFuIeag==", + "dependencies": { + "psl": "^1.1.33", + "punycode": "^2.1.1", + "universalify": "^0.2.0", + "url-parse": "^1.5.3" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/tough-cookie/node_modules/universalify": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz", + "integrity": "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==", + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/tsconfig-paths": { + "version": "3.15.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", + "integrity": "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==", + "dev": true, + "dependencies": { + "@types/json5": "^0.0.29", + "json5": "^1.0.2", + "minimist": "^1.2.6", + "strip-bom": "^3.0.0" + } + }, + "node_modules/tslib": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz", + "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==" + }, + "node_modules/tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", + "dependencies": { + "safe-buffer": "^5.0.1" + }, + "engines": { + "node": "*" + } + }, + "node_modules/tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==" + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/typed-array-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.2.tgz", + "integrity": "sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/typed-array-byte-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.1.tgz", + "integrity": "sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-byte-offset": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.2.tgz", + "integrity": "sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA==", + "dev": true, + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-length": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.6.tgz", + "integrity": "sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13", + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/unbox-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", + "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-bigints": "^1.0.2", + "has-symbols": "^1.0.3", + "which-boxed-primitive": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "optional": true + }, + "node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/untildify": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/untildify/-/untildify-4.0.0.tgz", + "integrity": "sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==", + "engines": { + "node": ">=8" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/url-parse": { + "version": "1.5.10", + "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz", + "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==", + "dependencies": { + "querystringify": "^2.1.1", + "requires-port": "^1.0.0" + } + }, + "node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==", + "engines": [ + "node >=0.6.0" + ], + "dependencies": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/which-boxed-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", + "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", + "dev": true, + "dependencies": { + "is-bigint": "^1.0.1", + "is-boolean-object": "^1.1.0", + "is-number-object": "^1.0.4", + "is-string": "^1.0.5", + "is-symbol": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-typed-array": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.15.tgz", + "integrity": "sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==", + "dev": true, + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/word-wrap": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" + }, + "node_modules/yauzl": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", + "integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==", + "dependencies": { + "buffer-crc32": "~0.2.3", + "fd-slicer": "~1.1.0" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/zone.js": { + "version": "0.14.7", + "resolved": "https://registry.npmjs.org/zone.js/-/zone.js-0.14.7.tgz", + "integrity": "sha512-0w6DGkX2BPuiK/NLf+4A8FLE43QwBfuqz2dVgi/40Rj1WmqUskCqj329O/pwrqFJLG5X8wkeG2RhIAro441xtg==", + "peer": true + } + } +} diff --git a/src/cypress/package.json b/src/cypress/package.json new file mode 100644 index 0000000000..26d1c5ee0e --- /dev/null +++ b/src/cypress/package.json @@ -0,0 +1,38 @@ +{ + "name": "mapacultural", + "version": "1.0.0", + "description": "[![Join the chat at https://t.me/joinchat/WCYOkiRbAWmxQM2y](https://patrolavia.github.io/telegram-badge/chat.png)](https://t.me/joinchat/WCYOkiRbAWmxQM2y)", + "main": "cypress.config.js", + "directories": { + "test": "tests" + }, + "scripts": { + "cypress:open": "cypress open", + "cypress:run": "cypress run" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/secultce/mapacultural.git" + }, + "keywords": [], + "author": "", + "license": "ISC", + "bugs": { + "url": "https://github.com/secultce/mapacultural/issues" + }, + "homepage": "https://github.com/secultce/mapacultural#readme", + "dependencies": { + "cypress": "^13.11.0", + "ng-recaptcha": "^13.2.1" + }, + "devDependencies": { + "eslint": "^8.56.0", + "eslint-config-semistandard": "^17.0.0", + "eslint-config-standard": "^17.1.0", + "eslint-plugin-cypress": "^2.15.1", + "eslint-plugin-import": "^2.29.1", + "eslint-plugin-n": "^15.7.0", + "eslint-plugin-promise": "^6.1.1", + "husky": "^9.0.11" + } +} diff --git a/src/db-updates.php b/src/db-updates.php index dbf948eb80..ef24173788 100644 --- a/src/db-updates.php +++ b/src/db-updates.php @@ -372,6 +372,10 @@ function __try($sql, $cb = null){ $conn->executeQuery("INSERT INTO seal_relation SELECT nextval('seal_relation_id_seq'), 1, id, CURRENT_TIMESTAMP, 1, 'MapasCulturais\Entities\Event', $agent_id FROM event WHERE is_verified = 't';"); }, + 'fix seal sequence' => function () use($conn) { + $conn->executeQuery("ALTER SEQUENCE seal_id_seq RESTART WITH 2;"); + }, + 'create update timestamp entities' => function () use($conn) { if(__column_exists('agent', 'update_timestamp')){ echo " ALREADY APPLIED update_timestamp FIELD CREATION ON agent TABLE. "; diff --git a/src/modules/Entities/components/entity-terms/script.js b/src/modules/Entities/components/entity-terms/script.js index b2d6bc8f81..ca5b7b4e39 100644 --- a/src/modules/Entities/components/entity-terms/script.js +++ b/src/modules/Entities/components/entity-terms/script.js @@ -19,6 +19,7 @@ app.component('entity-terms', { terms: this.definition.terms || [], label: this.title || this.definition.name, filter: '', + warningMessage: false, }; }, @@ -84,8 +85,14 @@ app.component('entity-terms', { methods: { insertTag(toggleModal) { - this.addTerm(this.filter); + if (0 === this.filter.trim().length) { + this.warningMessage = true; + return; + } + + this.addTerm(this.filter.trim()); this.filter = ''; + this.warningMessage = false; toggleModal(); }, loadTerms() { diff --git a/src/modules/Entities/components/entity-terms/template.php b/src/modules/Entities/components/entity-terms/template.php index bd01272fa8..fb9c2ccee1 100644 --- a/src/modules/Entities/components/entity-terms/template.php +++ b/src/modules/Entities/components/entity-terms/template.php @@ -29,6 +29,7 @@