From 34169a9febd84a0cd532cd117ad326b48e347f02 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?J=C3=A9r=C3=A9my=20Munsch?=
Date: Wed, 12 Aug 2026 15:45:29 +0200
Subject: [PATCH] feat(api): implement tracer bullet for employees and OpenAPI
specification
---
.editorconfig | 35 +
.env.example | 82 +
.env.testing | 38 +
.gitattributes | 11 +
.gitignore | 27 +
.intellipest/_pest-helper.php | 57 +
README.md | 92 -
artisan | 18 +
bootstrap/app.php | 45 +
bootstrap/cache/.gitignore | 2 +
bootstrap/middlewares.php | 12 +
bootstrap/providers.php | 11 +
composer.json | 111 +
composer.lock | 11763 ++++++++++++++++
config/app.php | 128 +
config/auth.php | 119 +
config/cache.php | 138 +
config/database.php | 208 +
config/filesystems.php | 82 +
config/ide-helper.php | 379 +
config/logging.php | 134 +
config/mail.php | 120 +
config/queue.php | 131 +
config/sanctum.php | 89 +
config/services.php | 40 +
config/session.php | 235 +
config/spectator.php | 83 +
config/view.php | 38 +
database/.gitignore | 1 +
database/factories/EmployeeFactory.php | 35 +
database/factories/UserFactory.php | 46 +
.../0001_01_01_000000_create_users_table.php | 51 +
.../0001_01_01_000001_create_cache_table.php | 37 +
.../0001_01_01_000002_create_jobs_table.php | 61 +
...39_create_personal_access_tokens_table.php | 35 +
..._08_10_145347_create_api_clients_table.php | 35 +
...26_08_11_000000_create_employees_table.php | 47 +
database/seeders/DatabaseSeeder.php | 21 +
database/seeders/EmployeeSeeder.php | 84 +
documentation/Bruno/Arcadia Api/.gitignore | 9 +
.../Bruno/Arcadia Api/Api/Api Root.yml | 15 +
.../Api/V1/Employees/Get Employee.yml | 19 +
.../Api/V1/Employees/List Employees.yml | 62 +
.../Arcadia Api/Api/V1/Employees/folder.yml | 7 +
.../Bruno/Arcadia Api/Api/V1/OpenApi Spec.yml | 15 +
.../Bruno/Arcadia Api/Api/V1/Ping.yml | 15 +
.../Bruno/Arcadia Api/Api/V1/Root.yml | 15 +
.../Bruno/Arcadia Api/Api/V1/folder.yml | 7 +
.../Bruno/Arcadia Api/Api/folder.yml | 7 +
documentation/Bruno/Arcadia Api/Root Url.yml | 15 +
.../Arcadia Api/environments/Local Dev.yml | 11 +
.../Bruno/Arcadia Api/opencollection.yml | 10 +
documentation/OpenApi/openapi.yaml | 546 +
documentation/OpenApi/original-endpoint.yaml | 819 ++
phpcs.xml | 67 +
phpstan.neon | 16 +
phpunit.xml | 22 +
pint.json | 77 +
public/.htaccess | 25 +
public/favicon.ico | 0
public/index.php | 21 +
public/robots.txt | 2 +
rector.php | 34 +
routes/api.php | 15 +
routes/apiv1.php | 21 +
routes/console.php | 3 +
routes/web.php | 10 +
.../Employees/Find/EmployeeShowPresenter.php | 20 +
.../Employees/Find/EmployeeShowView.php | 38 +
.../Usecase/Employees/Find/FindEmployee.php | 43 +
.../Usecase/Employees/Find/Input.php | 16 +
.../Usecase/Employees/Find/Output.php | 24 +
.../FindAll/EmployeesIndexPresenter.php | 20 +
.../Employees/FindAll/EmployeesIndexView.php | 32 +
.../Employees/FindAll/FindAllEmployees.php | 53 +
.../Usecase/Employees/FindAll/Input.php | 18 +
.../Usecase/Employees/FindAll/Output.php | 22 +
.../Employees/FindAll/PaginatedEmployee.php | 40 +
src/Domain/Exceptions/NotFoundException.php | 13 +
src/Domain/Models/Entities/Employee.php | 36 +
src/Domain/Models/ValueObjects/BrandCode.php | 21 +
.../Employees/EmployeeSortColumn.php | 15 +
.../ValueObjects/Employees/EmployeeSorter.php | 14 +
.../Entities/ArcadiaEmployeeId.php | 22 +
.../Models/ValueObjects/EstablishmentCode.php | 20 +
.../Models/ValueObjects/Inco/Additive.php | 47 +
.../Models/ValueObjects/Inco/Allegations.php | 85 +
.../Models/ValueObjects/Inco/Allergen.php | 33 +
.../Models/ValueObjects/Inco/IncoWeight.php | 29 +
.../Models/ValueObjects/Inco/Ingredients.php | 52 +
.../Models/ValueObjects/Inco/Nutriscore.php | 34 +
.../ValueObjects/Inco/PortionAmount.php | 88 +
.../Models/ValueObjects/Inco/PortionType.php | 31 +
.../ValueObjects/Inco/StorageCondition.php | 28 +
.../IncoCompo/AbstractIncoCompoPartDto.php | 14 +
.../ValueObjects/IncoCompo/AcideGras.php | 75 +
.../ValueObjects/IncoCompo/AcidesAmines.php | 15 +
.../IncoCompo/ApportsReference.php | 22 +
.../IncoCompo/ComposesSpeciaux.php | 16 +
.../Models/ValueObjects/IncoCompo/Energie.php | 20 +
.../IncoCompo/FruitLegumeNoix.php | 20 +
.../ValueObjects/IncoCompo/GlucidesDetail.php | 26 +
.../ValueObjects/IncoCompo/Identification.php | 15 +
.../IncoCompo/IncoCompoPartDto.php | 10 +
.../IncoCompo/MacronutrimentsPortion.php | 27 +
.../IncoCompo/MacronutrimentsRef.php | 27 +
.../ValueObjects/IncoCompo/Mineraux.php | 27 +
.../ValueObjects/IncoCompo/NutriScore.php | 22 +
.../IncoCompo/PointsNutriScore.php | 19 +
.../ValueObjects/IncoCompo/Vitamines.php | 26 +
.../Models/ValueObjects/IncoCompoId.php | 20 +
src/Domain/Models/ValueObjects/IncoId.php | 20 +
src/Domain/Models/ValueObjects/ServiceId.php | 23 +
src/Domain/Models/ValueObjects/SiteId.php | 23 +
.../Ports/Directories/EmployeeDirectory.php | 21 +
.../Directories/EloquentEmployeeDirectory.php | 118 +
src/Infra/Database/Models/ApiClient.php | 33 +
src/Infra/Database/Models/Employee.php | 73 +
.../Http/Middleware/VerifyHmacSignature.php | 62 +
src/Infra/Providers/AppServiceProvider.php | 121 +
src/Infra/Providers/DomainServiceProvider.php | 21 +
src/Infra/Usecase/LaravelExecutor.php | 57 +
.../Api/Exceptions/ApiExceptionDispatcher.php | 32 +
.../Api/V1/Contracts/ApiResponse.php | 12 +
.../Api/V1/Contracts/ApiResponseDto.php | 9 +
.../Api/V1/Dto/Employees/EmployeeDto.php | 39 +
.../V1/Dto/Employees/PaginatedEmployee.php | 39 +
.../Api/V1/Exceptions/ApiErrorCode.php | 28 +
.../V1/Exceptions/ApiExceptionRenderer.php | 74 +
.../Employees/EmployeeShowController.php | 36 +
.../Employees/EmployeesIndexController.php | 36 +
.../Employees/EmployeeShowRequest.php | 39 +
.../Employees/EmployeesIndexRequest.php | 82 +
.../Employees/EmployeeShowResponse.php | 28 +
.../Employees/EmployeesIndexResponse.php | 58 +
.../Web/Exceptions/WebExceptionRenderer.php | 26 +
.../ErrorDocumentationController.php | 19 +
.../Web/Http/Controllers/HomeController.php | 15 +
.../views/errors/docs/bad-request.blade.php | 7 +
.../errors/docs/internal-error.blade.php | 7 +
.../views/errors/docs/layout.blade.php | 25 +
.../views/errors/docs/not-found.blade.php | 12 +
.../errors/docs/validation-error.blade.php | 10 +
.../Web/resources/views/index.blade.php | 11 +
.../resources/views/layouts/head.blade.php | 29 +
.../resources/views/layouts/layout.blade.php | 21 +
src/Shared/DDD/Directory.php | 15 +
src/Shared/DDD/DomainEventDispatcher.php | 10 +
src/Shared/DDD/Entity.php | 14 +
src/Shared/DDD/EntityId.php | 28 +
src/Shared/DDD/Equatable.php | 10 +
src/Shared/DDD/Event.php | 9 +
src/Shared/DDD/Repository.php | 17 +
.../DDD/Usecase/Builder/BuilderStepBuild.php | 10 +
.../DDD/Usecase/Builder/BuilderStepInput.php | 14 +
.../Usecase/Builder/BuilderStepPresenter.php | 14 +
.../Usecase/Builder/BuilderStepUsecase.php | 17 +
.../DDD/Usecase/Builder/UsecaseBuilder.php | 20 +
.../Builder/UsecaseExecutionBuilder.php | 85 +
.../DDD/Usecase/Builder/UsecaseExecutor.php | 22 +
src/Shared/DDD/Usecase/Executor.php | 10 +
src/Shared/DDD/Usecase/Input.php | 9 +
src/Shared/DDD/Usecase/Output.php | 9 +
src/Shared/DDD/Usecase/Presenter.php | 19 +
src/Shared/DDD/Usecase/Usecase.php | 18 +
src/Shared/Enums/BaseEnum.php | 171 +
src/Shared/Helpers/DatesHelper.php | 119 +
src/Shared/Helpers/UuidHelper.php | 47 +
src/Shared/Paginated.php | 40 +
src/Shared/Pagination.php | 97 +
storage/app/.gitignore | 4 +
storage/app/private/.gitignore | 2 +
storage/app/public/.gitignore | 2 +
storage/framework/.gitignore | 9 +
storage/framework/cache/.gitignore | 3 +
storage/framework/cache/data/.gitignore | 2 +
storage/framework/sessions/.gitignore | 2 +
storage/framework/testing/.gitignore | 2 +
storage/framework/views/.gitignore | 2 +
storage/logs/.gitignore | 2 +
tests/Architecture/ApplicationTest.php | 27 +
tests/Architecture/CodingStandardsTest.php | 57 +
tests/Architecture/DomainTest.php | 97 +
tests/Architecture/InfraTest.php | 31 +
tests/Architecture/NamingConventionsTest.php | 47 +
tests/Architecture/PresentationTest.php | 31 +
tests/CreatesApplication.php | 25 +
tests/Feature/ErrorDocumentationTest.php | 37 +
tests/Feature/ExampleTest.php | 19 +
tests/Feature/OpenApiConformanceTest.php | 95 +
tests/Pest.php | 39 +
tests/TestCase.php | 14 +
tests/Unit/Domain/ArcadiaEmployeeIdTest.php | 57 +
tests/Unit/ExampleTest.php | 19 +
194 files changed, 20484 insertions(+), 92 deletions(-)
create mode 100644 .editorconfig
create mode 100644 .env.example
create mode 100644 .env.testing
create mode 100644 .gitattributes
create mode 100644 .gitignore
create mode 100644 .intellipest/_pest-helper.php
create mode 100755 artisan
create mode 100644 bootstrap/app.php
create mode 100644 bootstrap/cache/.gitignore
create mode 100644 bootstrap/middlewares.php
create mode 100644 bootstrap/providers.php
create mode 100644 composer.json
create mode 100644 composer.lock
create mode 100644 config/app.php
create mode 100644 config/auth.php
create mode 100644 config/cache.php
create mode 100644 config/database.php
create mode 100644 config/filesystems.php
create mode 100644 config/ide-helper.php
create mode 100644 config/logging.php
create mode 100644 config/mail.php
create mode 100644 config/queue.php
create mode 100644 config/sanctum.php
create mode 100644 config/services.php
create mode 100644 config/session.php
create mode 100644 config/spectator.php
create mode 100644 config/view.php
create mode 100644 database/.gitignore
create mode 100644 database/factories/EmployeeFactory.php
create mode 100644 database/factories/UserFactory.php
create mode 100644 database/migrations/0001_01_01_000000_create_users_table.php
create mode 100644 database/migrations/0001_01_01_000001_create_cache_table.php
create mode 100644 database/migrations/0001_01_01_000002_create_jobs_table.php
create mode 100644 database/migrations/2026_08_10_145239_create_personal_access_tokens_table.php
create mode 100644 database/migrations/2026_08_10_145347_create_api_clients_table.php
create mode 100644 database/migrations/2026_08_11_000000_create_employees_table.php
create mode 100644 database/seeders/DatabaseSeeder.php
create mode 100644 database/seeders/EmployeeSeeder.php
create mode 100644 documentation/Bruno/Arcadia Api/.gitignore
create mode 100644 documentation/Bruno/Arcadia Api/Api/Api Root.yml
create mode 100644 documentation/Bruno/Arcadia Api/Api/V1/Employees/Get Employee.yml
create mode 100644 documentation/Bruno/Arcadia Api/Api/V1/Employees/List Employees.yml
create mode 100644 documentation/Bruno/Arcadia Api/Api/V1/Employees/folder.yml
create mode 100644 documentation/Bruno/Arcadia Api/Api/V1/OpenApi Spec.yml
create mode 100644 documentation/Bruno/Arcadia Api/Api/V1/Ping.yml
create mode 100644 documentation/Bruno/Arcadia Api/Api/V1/Root.yml
create mode 100644 documentation/Bruno/Arcadia Api/Api/V1/folder.yml
create mode 100644 documentation/Bruno/Arcadia Api/Api/folder.yml
create mode 100644 documentation/Bruno/Arcadia Api/Root Url.yml
create mode 100644 documentation/Bruno/Arcadia Api/environments/Local Dev.yml
create mode 100644 documentation/Bruno/Arcadia Api/opencollection.yml
create mode 100644 documentation/OpenApi/openapi.yaml
create mode 100644 documentation/OpenApi/original-endpoint.yaml
create mode 100644 phpcs.xml
create mode 100644 phpstan.neon
create mode 100644 phpunit.xml
create mode 100644 pint.json
create mode 100644 public/.htaccess
create mode 100644 public/favicon.ico
create mode 100644 public/index.php
create mode 100644 public/robots.txt
create mode 100644 rector.php
create mode 100644 routes/api.php
create mode 100644 routes/apiv1.php
create mode 100644 routes/console.php
create mode 100644 routes/web.php
create mode 100644 src/Application/Usecase/Employees/Find/EmployeeShowPresenter.php
create mode 100644 src/Application/Usecase/Employees/Find/EmployeeShowView.php
create mode 100644 src/Application/Usecase/Employees/Find/FindEmployee.php
create mode 100644 src/Application/Usecase/Employees/Find/Input.php
create mode 100644 src/Application/Usecase/Employees/Find/Output.php
create mode 100644 src/Application/Usecase/Employees/FindAll/EmployeesIndexPresenter.php
create mode 100644 src/Application/Usecase/Employees/FindAll/EmployeesIndexView.php
create mode 100644 src/Application/Usecase/Employees/FindAll/FindAllEmployees.php
create mode 100644 src/Application/Usecase/Employees/FindAll/Input.php
create mode 100644 src/Application/Usecase/Employees/FindAll/Output.php
create mode 100644 src/Application/Usecase/Employees/FindAll/PaginatedEmployee.php
create mode 100644 src/Domain/Exceptions/NotFoundException.php
create mode 100644 src/Domain/Models/Entities/Employee.php
create mode 100644 src/Domain/Models/ValueObjects/BrandCode.php
create mode 100644 src/Domain/Models/ValueObjects/Employees/EmployeeSortColumn.php
create mode 100644 src/Domain/Models/ValueObjects/Employees/EmployeeSorter.php
create mode 100644 src/Domain/Models/ValueObjects/Entities/ArcadiaEmployeeId.php
create mode 100644 src/Domain/Models/ValueObjects/EstablishmentCode.php
create mode 100644 src/Domain/Models/ValueObjects/Inco/Additive.php
create mode 100644 src/Domain/Models/ValueObjects/Inco/Allegations.php
create mode 100644 src/Domain/Models/ValueObjects/Inco/Allergen.php
create mode 100644 src/Domain/Models/ValueObjects/Inco/IncoWeight.php
create mode 100644 src/Domain/Models/ValueObjects/Inco/Ingredients.php
create mode 100644 src/Domain/Models/ValueObjects/Inco/Nutriscore.php
create mode 100644 src/Domain/Models/ValueObjects/Inco/PortionAmount.php
create mode 100644 src/Domain/Models/ValueObjects/Inco/PortionType.php
create mode 100644 src/Domain/Models/ValueObjects/Inco/StorageCondition.php
create mode 100644 src/Domain/Models/ValueObjects/IncoCompo/AbstractIncoCompoPartDto.php
create mode 100644 src/Domain/Models/ValueObjects/IncoCompo/AcideGras.php
create mode 100644 src/Domain/Models/ValueObjects/IncoCompo/AcidesAmines.php
create mode 100644 src/Domain/Models/ValueObjects/IncoCompo/ApportsReference.php
create mode 100644 src/Domain/Models/ValueObjects/IncoCompo/ComposesSpeciaux.php
create mode 100644 src/Domain/Models/ValueObjects/IncoCompo/Energie.php
create mode 100644 src/Domain/Models/ValueObjects/IncoCompo/FruitLegumeNoix.php
create mode 100644 src/Domain/Models/ValueObjects/IncoCompo/GlucidesDetail.php
create mode 100644 src/Domain/Models/ValueObjects/IncoCompo/Identification.php
create mode 100644 src/Domain/Models/ValueObjects/IncoCompo/IncoCompoPartDto.php
create mode 100644 src/Domain/Models/ValueObjects/IncoCompo/MacronutrimentsPortion.php
create mode 100644 src/Domain/Models/ValueObjects/IncoCompo/MacronutrimentsRef.php
create mode 100644 src/Domain/Models/ValueObjects/IncoCompo/Mineraux.php
create mode 100644 src/Domain/Models/ValueObjects/IncoCompo/NutriScore.php
create mode 100644 src/Domain/Models/ValueObjects/IncoCompo/PointsNutriScore.php
create mode 100644 src/Domain/Models/ValueObjects/IncoCompo/Vitamines.php
create mode 100644 src/Domain/Models/ValueObjects/IncoCompoId.php
create mode 100644 src/Domain/Models/ValueObjects/IncoId.php
create mode 100644 src/Domain/Models/ValueObjects/ServiceId.php
create mode 100644 src/Domain/Models/ValueObjects/SiteId.php
create mode 100644 src/Domain/Ports/Directories/EmployeeDirectory.php
create mode 100644 src/Infra/Adapters/Directories/EloquentEmployeeDirectory.php
create mode 100644 src/Infra/Database/Models/ApiClient.php
create mode 100644 src/Infra/Database/Models/Employee.php
create mode 100644 src/Infra/Http/Middleware/VerifyHmacSignature.php
create mode 100644 src/Infra/Providers/AppServiceProvider.php
create mode 100644 src/Infra/Providers/DomainServiceProvider.php
create mode 100644 src/Infra/Usecase/LaravelExecutor.php
create mode 100644 src/Presentation/Api/Exceptions/ApiExceptionDispatcher.php
create mode 100644 src/Presentation/Api/V1/Contracts/ApiResponse.php
create mode 100644 src/Presentation/Api/V1/Contracts/ApiResponseDto.php
create mode 100644 src/Presentation/Api/V1/Dto/Employees/EmployeeDto.php
create mode 100644 src/Presentation/Api/V1/Dto/Employees/PaginatedEmployee.php
create mode 100644 src/Presentation/Api/V1/Exceptions/ApiErrorCode.php
create mode 100644 src/Presentation/Api/V1/Exceptions/ApiExceptionRenderer.php
create mode 100644 src/Presentation/Api/V1/Http/Controllers/Employees/EmployeeShowController.php
create mode 100644 src/Presentation/Api/V1/Http/Controllers/Employees/EmployeesIndexController.php
create mode 100644 src/Presentation/Api/V1/Http/Requests/Employees/EmployeeShowRequest.php
create mode 100644 src/Presentation/Api/V1/Http/Requests/Employees/EmployeesIndexRequest.php
create mode 100644 src/Presentation/Api/V1/Http/Responses/Employees/EmployeeShowResponse.php
create mode 100644 src/Presentation/Api/V1/Http/Responses/Employees/EmployeesIndexResponse.php
create mode 100644 src/Presentation/Web/Exceptions/WebExceptionRenderer.php
create mode 100644 src/Presentation/Web/Http/Controllers/ErrorDocumentationController.php
create mode 100644 src/Presentation/Web/Http/Controllers/HomeController.php
create mode 100644 src/Presentation/Web/resources/views/errors/docs/bad-request.blade.php
create mode 100644 src/Presentation/Web/resources/views/errors/docs/internal-error.blade.php
create mode 100644 src/Presentation/Web/resources/views/errors/docs/layout.blade.php
create mode 100644 src/Presentation/Web/resources/views/errors/docs/not-found.blade.php
create mode 100644 src/Presentation/Web/resources/views/errors/docs/validation-error.blade.php
create mode 100644 src/Presentation/Web/resources/views/index.blade.php
create mode 100644 src/Presentation/Web/resources/views/layouts/head.blade.php
create mode 100644 src/Presentation/Web/resources/views/layouts/layout.blade.php
create mode 100644 src/Shared/DDD/Directory.php
create mode 100644 src/Shared/DDD/DomainEventDispatcher.php
create mode 100644 src/Shared/DDD/Entity.php
create mode 100644 src/Shared/DDD/EntityId.php
create mode 100644 src/Shared/DDD/Equatable.php
create mode 100644 src/Shared/DDD/Event.php
create mode 100644 src/Shared/DDD/Repository.php
create mode 100644 src/Shared/DDD/Usecase/Builder/BuilderStepBuild.php
create mode 100644 src/Shared/DDD/Usecase/Builder/BuilderStepInput.php
create mode 100644 src/Shared/DDD/Usecase/Builder/BuilderStepPresenter.php
create mode 100644 src/Shared/DDD/Usecase/Builder/BuilderStepUsecase.php
create mode 100644 src/Shared/DDD/Usecase/Builder/UsecaseBuilder.php
create mode 100644 src/Shared/DDD/Usecase/Builder/UsecaseExecutionBuilder.php
create mode 100644 src/Shared/DDD/Usecase/Builder/UsecaseExecutor.php
create mode 100644 src/Shared/DDD/Usecase/Executor.php
create mode 100644 src/Shared/DDD/Usecase/Input.php
create mode 100644 src/Shared/DDD/Usecase/Output.php
create mode 100644 src/Shared/DDD/Usecase/Presenter.php
create mode 100644 src/Shared/DDD/Usecase/Usecase.php
create mode 100644 src/Shared/Enums/BaseEnum.php
create mode 100644 src/Shared/Helpers/DatesHelper.php
create mode 100644 src/Shared/Helpers/UuidHelper.php
create mode 100644 src/Shared/Paginated.php
create mode 100644 src/Shared/Pagination.php
create mode 100644 storage/app/.gitignore
create mode 100644 storage/app/private/.gitignore
create mode 100644 storage/app/public/.gitignore
create mode 100644 storage/framework/.gitignore
create mode 100644 storage/framework/cache/.gitignore
create mode 100644 storage/framework/cache/data/.gitignore
create mode 100644 storage/framework/sessions/.gitignore
create mode 100644 storage/framework/testing/.gitignore
create mode 100644 storage/framework/views/.gitignore
create mode 100644 storage/logs/.gitignore
create mode 100644 tests/Architecture/ApplicationTest.php
create mode 100644 tests/Architecture/CodingStandardsTest.php
create mode 100644 tests/Architecture/DomainTest.php
create mode 100644 tests/Architecture/InfraTest.php
create mode 100644 tests/Architecture/NamingConventionsTest.php
create mode 100644 tests/Architecture/PresentationTest.php
create mode 100644 tests/CreatesApplication.php
create mode 100644 tests/Feature/ErrorDocumentationTest.php
create mode 100644 tests/Feature/ExampleTest.php
create mode 100644 tests/Feature/OpenApiConformanceTest.php
create mode 100644 tests/Pest.php
create mode 100644 tests/TestCase.php
create mode 100644 tests/Unit/Domain/ArcadiaEmployeeIdTest.php
create mode 100644 tests/Unit/ExampleTest.php
diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 0000000..5395f61
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,35 @@
+root = true
+
+[*]
+charset = utf-8
+end_of_line = lf
+indent_size = 2
+indent_style = space
+insert_final_newline = true
+trim_trailing_whitespace = true
+
+[*.md]
+trim_trailing_whitespace = false
+
+[*.{php,json}]
+indent_size = 4
+
+[*.blade.php]
+indent_size = 2
+
+[*.{yml,yaml}]
+indent_size = 2
+
+[{compose,docker-compose}.{yml,yaml}]
+indent_size = 2
+
+[*.scss]
+indent_size = 2
+quote_type = single
+
+[*.css]
+indent_size = 2
+quote_type = single
+
+[*.vue]
+indent_size = 2
diff --git a/.env.example b/.env.example
new file mode 100644
index 0000000..7f44ea1
--- /dev/null
+++ b/.env.example
@@ -0,0 +1,82 @@
+APP_NAME=Laravel
+APP_ENV=local
+APP_KEY=
+APP_DEBUG=true
+APP_URL=http://localhost
+
+APP_LOCALE=en
+APP_FALLBACK_LOCALE=en
+APP_FAKER_LOCALE=en_US
+
+APP_MAINTENANCE_DRIVER=file
+# APP_MAINTENANCE_STORE=database
+
+# PHP_CLI_SERVER_WORKERS=4
+
+BCRYPT_ROUNDS=12
+
+LOG_CHANNEL=stack
+LOG_STACK=single
+LOG_DEPRECATIONS_CHANNEL=null
+LOG_LEVEL=debug
+
+DB_CONNECTION=sqlite
+# DB_URL=
+# DB_HOST=127.0.0.1
+# DB_PORT=3306
+# DB_DATABASE=laravel
+# DB_USERNAME=root
+# DB_PASSWORD=
+# DB_SOCKET=
+# DB_CHARSET=utf8mb4
+# DB_COLLATION=utf8mb4_unicode_ci
+# MYSQL_ATTR_SSL_CA=
+
+ARCADIA_DB_CONNECTION=mysql
+# ARCADIA_DB_URL=
+ARCADIA_DB_HOST=127.0.0.1
+ARCADIA_DB_PORT=3306
+ARCADIA_DB=arcadia
+ARCADIA_DB_USERNAME=root
+ARCADIA_DB_PASSWORD=
+# ARCADIA_DB_SOCKET=
+# ARCADIA_DB_CHARSET=utf8mb4
+# ARCADIA_DB_COLLATION=utf8mb4_unicode_ci
+# ARCADIA_DB_SSL_CA=
+
+SESSION_DRIVER=database
+SESSION_LIFETIME=120
+SESSION_ENCRYPT=false
+SESSION_PATH=/
+SESSION_DOMAIN=null
+
+BROADCAST_CONNECTION=log
+FILESYSTEM_DISK=local
+QUEUE_CONNECTION=database
+
+CACHE_STORE=database
+# CACHE_PREFIX=
+
+MEMCACHED_HOST=127.0.0.1
+
+REDIS_CLIENT=phpredis
+REDIS_HOST=127.0.0.1
+REDIS_PASSWORD=null
+REDIS_PORT=6379
+
+MAIL_MAILER=log
+MAIL_SCHEME=null
+MAIL_HOST=127.0.0.1
+MAIL_PORT=2525
+MAIL_USERNAME=null
+MAIL_PASSWORD=null
+MAIL_FROM_ADDRESS="hello@example.com"
+MAIL_FROM_NAME="${APP_NAME}"
+
+AWS_ACCESS_KEY_ID=
+AWS_SECRET_ACCESS_KEY=
+AWS_DEFAULT_REGION=us-east-1
+AWS_BUCKET=
+AWS_USE_PATH_STYLE_ENDPOINT=false
+
+VITE_APP_NAME="${APP_NAME}"
diff --git a/.env.testing b/.env.testing
new file mode 100644
index 0000000..86eff9b
--- /dev/null
+++ b/.env.testing
@@ -0,0 +1,38 @@
+APP_NAME="Arcadia Api"
+APP_ENV=testing
+APP_KEY=base64:2ik2NRSDu8/Lxsxzdnnom3xWEglXe+cGd/7beOt/eXY=
+APP_DEBUG=true
+APP_URL=http://localhost
+
+APP_LOCALE=en
+APP_FALLBACK_LOCALE=en
+APP_FAKER_LOCALE=en_US
+APP_MAINTENANCE_DRIVER=file
+
+BCRYPT_ROUNDS=4
+
+LOG_CHANNEL=stack
+LOG_STACK=single
+LOG_DEPRECATIONS_CHANNEL=null
+LOG_LEVEL=debug
+
+DB_CONNECTION=sqlite
+DB_DATABASE=:memory:
+
+ARCADIA_DB_CONNECTION=sqlite
+
+SESSION_DRIVER=array
+SESSION_LIFETIME=120
+SESSION_ENCRYPT=false
+
+BROADCAST_CONNECTION=null
+FILESYSTEM_DISK=local
+QUEUE_CONNECTION=sync
+CACHE_STORE=array
+MAIL_MAILER=array
+
+SPEC_PATH=documentation/OpenApi
+
+PULSE_ENABLED=false
+TELESCOPE_ENABLED=false
+NIGHTWATCH_ENABLED=false
diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 0000000..fcb21d3
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1,11 @@
+* text=auto eol=lf
+
+*.blade.php diff=html
+*.css diff=css
+*.html diff=html
+*.md diff=markdown
+*.php diff=php
+
+/.github export-ignore
+CHANGELOG.md export-ignore
+.styleci.yml export-ignore
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..7be55e2
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,27 @@
+*.log
+.DS_Store
+.env
+.env.backup
+.env.production
+.phpactor.json
+.phpunit.result.cache
+/.codex
+/.cursor/
+/.idea
+/.nova
+/.phpunit.cache
+/.vscode
+/.zed
+/auth.json
+/node_modules
+/public/build
+/public/fonts-manifest.dev.json
+/public/hot
+/public/storage
+/storage/*.key
+/storage/pail
+/vendor
+_ide_helper.php
+Homestead.json
+Homestead.yaml
+Thumbs.db
diff --git a/.intellipest/_pest-helper.php b/.intellipest/_pest-helper.php
new file mode 100644
index 0000000..63772c0
--- /dev/null
+++ b/.intellipest/_pest-helper.php
@@ -0,0 +1,57 @@
+handleCommand(new ArgvInput);
+
+exit($status);
diff --git a/bootstrap/app.php b/bootstrap/app.php
new file mode 100644
index 0000000..0ae9ceb
--- /dev/null
+++ b/bootstrap/app.php
@@ -0,0 +1,45 @@
+withRouting(
+ web: __DIR__ . '/../routes/web.php',
+ api: __DIR__ . '/../routes/api.php',
+ commands: __DIR__ . '/../routes/console.php',
+ health: '/up',
+ )
+ ->withMiddleware(require __DIR__ . '/middlewares.php')
+ ->withExceptions(function (Exceptions $exceptions): void {
+ $exceptions->reportable(function (\Throwable $e): void {
+ if (app()->bound(HubInterface::class)) {
+ resolve(HubInterface::class)->captureException($e);
+ }
+ });
+
+ $exceptions->render(function (\Throwable $e, Request $request) {
+ $apiDispatcher = resolve(ApiExceptionDispatcher::class);
+ if ($apiResponse = $apiDispatcher->render($e, $request)) {
+ return $apiResponse;
+ }
+
+ $webRenderer = resolve(WebExceptionRenderer::class);
+ if ($webResponse = $webRenderer->render($e, $request)) {
+ return $webResponse;
+ }
+
+ return null;
+ });
+
+ $exceptions->shouldRenderJsonWhen(
+ fn (Request $request) => $request->is('api/*'),
+ );
+ })->create();
diff --git a/bootstrap/cache/.gitignore b/bootstrap/cache/.gitignore
new file mode 100644
index 0000000..d6b7ef3
--- /dev/null
+++ b/bootstrap/cache/.gitignore
@@ -0,0 +1,2 @@
+*
+!.gitignore
diff --git a/bootstrap/middlewares.php b/bootstrap/middlewares.php
new file mode 100644
index 0000000..aab5e65
--- /dev/null
+++ b/bootstrap/middlewares.php
@@ -0,0 +1,12 @@
+alias([
+ 'auth.hmac' => VerifyHmacSignature::class,
+ ]);
+};
diff --git a/bootstrap/providers.php b/bootstrap/providers.php
new file mode 100644
index 0000000..e8feb77
--- /dev/null
+++ b/bootstrap/providers.php
@@ -0,0 +1,11 @@
+=5.0.0"
+ },
+ "require-dev": {
+ "doctrine/dbal": "^4.0.0",
+ "nesbot/carbon": "^2.71.0 || ^3.0.0",
+ "phpunit/phpunit": "^10.3"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Carbon\\Doctrine\\": "src/Carbon/Doctrine/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "KyleKatarn",
+ "email": "kylekatarnls@gmail.com"
+ }
+ ],
+ "description": "Types to use Carbon in Doctrine",
+ "keywords": [
+ "carbon",
+ "date",
+ "datetime",
+ "doctrine",
+ "time"
+ ],
+ "support": {
+ "issues": "https://github.com/CarbonPHP/carbon-doctrine-types/issues",
+ "source": "https://github.com/CarbonPHP/carbon-doctrine-types/tree/3.2.0"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/kylekatarnls",
+ "type": "github"
+ },
+ {
+ "url": "https://opencollective.com/Carbon",
+ "type": "open_collective"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/nesbot/carbon",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2024-02-09T16:56:22+00:00"
+ },
+ {
+ "name": "dflydev/dot-access-data",
+ "version": "v3.0.3",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/dflydev/dflydev-dot-access-data.git",
+ "reference": "a23a2bf4f31d3518f3ecb38660c95715dfead60f"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/dflydev/dflydev-dot-access-data/zipball/a23a2bf4f31d3518f3ecb38660c95715dfead60f",
+ "reference": "a23a2bf4f31d3518f3ecb38660c95715dfead60f",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^7.1 || ^8.0"
+ },
+ "require-dev": {
+ "phpstan/phpstan": "^0.12.42",
+ "phpunit/phpunit": "^7.5 || ^8.5 || ^9.3",
+ "scrutinizer/ocular": "1.6.0",
+ "squizlabs/php_codesniffer": "^3.5",
+ "vimeo/psalm": "^4.0.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "3.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Dflydev\\DotAccessData\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Dragonfly Development Inc.",
+ "email": "info@dflydev.com",
+ "homepage": "http://dflydev.com"
+ },
+ {
+ "name": "Beau Simensen",
+ "email": "beau@dflydev.com",
+ "homepage": "http://beausimensen.com"
+ },
+ {
+ "name": "Carlos Frutos",
+ "email": "carlos@kiwing.it",
+ "homepage": "https://github.com/cfrutos"
+ },
+ {
+ "name": "Colin O'Dell",
+ "email": "colinodell@gmail.com",
+ "homepage": "https://www.colinodell.com"
+ }
+ ],
+ "description": "Given a deep data structure, access data by dot notation.",
+ "homepage": "https://github.com/dflydev/dflydev-dot-access-data",
+ "keywords": [
+ "access",
+ "data",
+ "dot",
+ "notation"
+ ],
+ "support": {
+ "issues": "https://github.com/dflydev/dflydev-dot-access-data/issues",
+ "source": "https://github.com/dflydev/dflydev-dot-access-data/tree/v3.0.3"
+ },
+ "time": "2024-07-08T12:26:09+00:00"
+ },
+ {
+ "name": "doctrine/inflector",
+ "version": "2.1.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/doctrine/inflector.git",
+ "reference": "6d6c96277ea252fc1304627204c3d5e6e15faa3b"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/doctrine/inflector/zipball/6d6c96277ea252fc1304627204c3d5e6e15faa3b",
+ "reference": "6d6c96277ea252fc1304627204c3d5e6e15faa3b",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^7.2 || ^8.0"
+ },
+ "require-dev": {
+ "doctrine/coding-standard": "^12.0 || ^13.0",
+ "phpstan/phpstan": "^1.12 || ^2.0",
+ "phpstan/phpstan-phpunit": "^1.4 || ^2.0",
+ "phpstan/phpstan-strict-rules": "^1.6 || ^2.0",
+ "phpunit/phpunit": "^8.5 || ^12.2"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Doctrine\\Inflector\\": "src"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Guilherme Blanco",
+ "email": "guilhermeblanco@gmail.com"
+ },
+ {
+ "name": "Roman Borschel",
+ "email": "roman@code-factory.org"
+ },
+ {
+ "name": "Benjamin Eberlei",
+ "email": "kontakt@beberlei.de"
+ },
+ {
+ "name": "Jonathan Wage",
+ "email": "jonwage@gmail.com"
+ },
+ {
+ "name": "Johannes Schmitt",
+ "email": "schmittjoh@gmail.com"
+ }
+ ],
+ "description": "PHP Doctrine Inflector is a small library that can perform string manipulations with regard to upper/lowercase and singular/plural forms of words.",
+ "homepage": "https://www.doctrine-project.org/projects/inflector.html",
+ "keywords": [
+ "inflection",
+ "inflector",
+ "lowercase",
+ "manipulation",
+ "php",
+ "plural",
+ "singular",
+ "strings",
+ "uppercase",
+ "words"
+ ],
+ "support": {
+ "issues": "https://github.com/doctrine/inflector/issues",
+ "source": "https://github.com/doctrine/inflector/tree/2.1.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%2Finflector",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2025-08-10T19:31:58+00:00"
+ },
+ {
+ "name": "doctrine/lexer",
+ "version": "3.0.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/doctrine/lexer.git",
+ "reference": "31ad66abc0fc9e1a1f2d9bc6a42668d2fbbcd6dd"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/doctrine/lexer/zipball/31ad66abc0fc9e1a1f2d9bc6a42668d2fbbcd6dd",
+ "reference": "31ad66abc0fc9e1a1f2d9bc6a42668d2fbbcd6dd",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^8.1"
+ },
+ "require-dev": {
+ "doctrine/coding-standard": "^12",
+ "phpstan/phpstan": "^1.10",
+ "phpunit/phpunit": "^10.5",
+ "psalm/plugin-phpunit": "^0.18.3",
+ "vimeo/psalm": "^5.21"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Doctrine\\Common\\Lexer\\": "src"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Guilherme Blanco",
+ "email": "guilhermeblanco@gmail.com"
+ },
+ {
+ "name": "Roman Borschel",
+ "email": "roman@code-factory.org"
+ },
+ {
+ "name": "Johannes Schmitt",
+ "email": "schmittjoh@gmail.com"
+ }
+ ],
+ "description": "PHP Doctrine Lexer parser library that can be used in Top-Down, Recursive Descent Parsers.",
+ "homepage": "https://www.doctrine-project.org/projects/lexer.html",
+ "keywords": [
+ "annotations",
+ "docblock",
+ "lexer",
+ "parser",
+ "php"
+ ],
+ "support": {
+ "issues": "https://github.com/doctrine/lexer/issues",
+ "source": "https://github.com/doctrine/lexer/tree/3.0.1"
+ },
+ "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%2Flexer",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2024-02-05T11:56:58+00:00"
+ },
+ {
+ "name": "dragonmantank/cron-expression",
+ "version": "v3.6.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/dragonmantank/cron-expression.git",
+ "reference": "d61a8a9604ec1f8c3d150d09db6ce98b32675013"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/dragonmantank/cron-expression/zipball/d61a8a9604ec1f8c3d150d09db6ce98b32675013",
+ "reference": "d61a8a9604ec1f8c3d150d09db6ce98b32675013",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^8.2|^8.3|^8.4|^8.5"
+ },
+ "replace": {
+ "mtdowling/cron-expression": "^1.0"
+ },
+ "require-dev": {
+ "phpstan/extension-installer": "^1.4.3",
+ "phpstan/phpstan": "^1.12.32|^2.1.31",
+ "phpunit/phpunit": "^8.5.48|^9.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "3.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Cron\\": "src/Cron/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Chris Tankersley",
+ "email": "chris@ctankersley.com",
+ "homepage": "https://github.com/dragonmantank"
+ }
+ ],
+ "description": "CRON for PHP: Calculate the next or previous run date and determine if a CRON expression is due",
+ "keywords": [
+ "cron",
+ "schedule"
+ ],
+ "support": {
+ "issues": "https://github.com/dragonmantank/cron-expression/issues",
+ "source": "https://github.com/dragonmantank/cron-expression/tree/v3.6.0"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/dragonmantank",
+ "type": "github"
+ }
+ ],
+ "time": "2025-10-31T18:51:33+00:00"
+ },
+ {
+ "name": "driftingly/rector-laravel",
+ "version": "2.5.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/driftingly/rector-laravel.git",
+ "reference": "0dbdd842dfdbc821cfe5f47ca7326e2502b2a107"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/driftingly/rector-laravel/zipball/0dbdd842dfdbc821cfe5f47ca7326e2502b2a107",
+ "reference": "0dbdd842dfdbc821cfe5f47ca7326e2502b2a107",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^7.4 || ^8.0",
+ "rector/rector": "^2.2.7",
+ "webmozart/assert": "^1.11 || ^2.0"
+ },
+ "type": "rector-extension",
+ "autoload": {
+ "psr-4": {
+ "RectorLaravel\\": "src"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "description": "Rector upgrades rules for Laravel Framework",
+ "support": {
+ "issues": "https://github.com/driftingly/rector-laravel/issues",
+ "source": "https://github.com/driftingly/rector-laravel/tree/2.5.0"
+ },
+ "time": "2026-06-02T16:22:14+00:00"
+ },
+ {
+ "name": "egulias/email-validator",
+ "version": "4.0.4",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/egulias/EmailValidator.git",
+ "reference": "d42c8731f0624ad6bdc8d3e5e9a4524f68801cfa"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/egulias/EmailValidator/zipball/d42c8731f0624ad6bdc8d3e5e9a4524f68801cfa",
+ "reference": "d42c8731f0624ad6bdc8d3e5e9a4524f68801cfa",
+ "shasum": ""
+ },
+ "require": {
+ "doctrine/lexer": "^2.0 || ^3.0",
+ "php": ">=8.1",
+ "symfony/polyfill-intl-idn": "^1.26"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^10.2",
+ "vimeo/psalm": "^5.12"
+ },
+ "suggest": {
+ "ext-intl": "PHP Internationalization Libraries are required to use the SpoofChecking validation"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "4.0.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Egulias\\EmailValidator\\": "src"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Eduardo Gulias Davis"
+ }
+ ],
+ "description": "A library for validating emails against several RFCs",
+ "homepage": "https://github.com/egulias/EmailValidator",
+ "keywords": [
+ "email",
+ "emailvalidation",
+ "emailvalidator",
+ "validation",
+ "validator"
+ ],
+ "support": {
+ "issues": "https://github.com/egulias/EmailValidator/issues",
+ "source": "https://github.com/egulias/EmailValidator/tree/4.0.4"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/egulias",
+ "type": "github"
+ }
+ ],
+ "time": "2025-03-06T22:45:56+00:00"
+ },
+ {
+ "name": "fruitcake/php-cors",
+ "version": "v1.4.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/fruitcake/php-cors.git",
+ "reference": "38aaa6c3fd4c157ffe2a4d10aa8b9b16ba8de379"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/fruitcake/php-cors/zipball/38aaa6c3fd4c157ffe2a4d10aa8b9b16ba8de379",
+ "reference": "38aaa6c3fd4c157ffe2a4d10aa8b9b16ba8de379",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^8.1",
+ "symfony/http-foundation": "^5.4|^6.4|^7.3|^8"
+ },
+ "require-dev": {
+ "phpstan/phpstan": "^2",
+ "phpunit/phpunit": "^9",
+ "squizlabs/php_codesniffer": "^4"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.3-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Fruitcake\\Cors\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Fruitcake",
+ "homepage": "https://fruitcake.nl"
+ },
+ {
+ "name": "Barryvdh",
+ "email": "barryvdh@gmail.com"
+ }
+ ],
+ "description": "Cross-origin resource sharing library for the Symfony HttpFoundation",
+ "homepage": "https://github.com/fruitcake/php-cors",
+ "keywords": [
+ "cors",
+ "laravel",
+ "symfony"
+ ],
+ "support": {
+ "issues": "https://github.com/fruitcake/php-cors/issues",
+ "source": "https://github.com/fruitcake/php-cors/tree/v1.4.0"
+ },
+ "funding": [
+ {
+ "url": "https://fruitcake.nl",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/barryvdh",
+ "type": "github"
+ }
+ ],
+ "time": "2025-12-03T09:33:47+00:00"
+ },
+ {
+ "name": "graham-campbell/result-type",
+ "version": "v1.1.4",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/GrahamCampbell/Result-Type.git",
+ "reference": "e01f4a821471308ba86aa202fed6698b6b695e3b"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/GrahamCampbell/Result-Type/zipball/e01f4a821471308ba86aa202fed6698b6b695e3b",
+ "reference": "e01f4a821471308ba86aa202fed6698b6b695e3b",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^7.2.5 || ^8.0",
+ "phpoption/phpoption": "^1.9.5"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^8.5.41 || ^9.6.22 || ^10.5.45 || ^11.5.7"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "GrahamCampbell\\ResultType\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Graham Campbell",
+ "email": "hello@gjcampbell.co.uk",
+ "homepage": "https://github.com/GrahamCampbell"
+ }
+ ],
+ "description": "An Implementation Of The Result Type",
+ "keywords": [
+ "Graham Campbell",
+ "GrahamCampbell",
+ "Result Type",
+ "Result-Type",
+ "result"
+ ],
+ "support": {
+ "issues": "https://github.com/GrahamCampbell/Result-Type/issues",
+ "source": "https://github.com/GrahamCampbell/Result-Type/tree/v1.1.4"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/GrahamCampbell",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/graham-campbell/result-type",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2025-12-27T19:43:20+00:00"
+ },
+ {
+ "name": "guzzlehttp/guzzle",
+ "version": "7.15.3",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/guzzle/guzzle.git",
+ "reference": "ae311b8f045ea93ce7b1c9cdb7cec06c53f944bc"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/guzzle/guzzle/zipball/ae311b8f045ea93ce7b1c9cdb7cec06c53f944bc",
+ "reference": "ae311b8f045ea93ce7b1c9cdb7cec06c53f944bc",
+ "shasum": ""
+ },
+ "require": {
+ "ext-json": "*",
+ "guzzlehttp/promises": "^2.5.2",
+ "guzzlehttp/psr7": "^2.13",
+ "php": "^7.2.5 || ^8.0",
+ "psr/http-client": "^1.0",
+ "symfony/deprecation-contracts": "^2.5 || ^3.0",
+ "symfony/polyfill-php80": "^1.25"
+ },
+ "provide": {
+ "psr/http-client-implementation": "1.0"
+ },
+ "require-dev": {
+ "bamarni/composer-bin-plugin": "^1.8.2",
+ "ext-curl": "*",
+ "guzzle/client-integration-tests": "3.0.3",
+ "guzzlehttp/test-server": "^0.7",
+ "php-http/message-factory": "^1.1",
+ "phpunit/phpunit": "^8.5.52 || ^9.6.34",
+ "psr/log": "^1.1 || ^2.0 || ^3.0"
+ },
+ "suggest": {
+ "ext-curl": "Required for CURL handler support",
+ "ext-intl": "Required for Internationalized Domain Name (IDN) support",
+ "psr/log": "Required for using the Log middleware"
+ },
+ "type": "library",
+ "extra": {
+ "bamarni-bin": {
+ "bin-links": true,
+ "forward-command": false
+ }
+ },
+ "autoload": {
+ "files": [
+ "src/functions_include.php"
+ ],
+ "psr-4": {
+ "GuzzleHttp\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Graham Campbell",
+ "email": "hello@gjcampbell.co.uk",
+ "homepage": "https://github.com/GrahamCampbell"
+ },
+ {
+ "name": "Michael Dowling",
+ "email": "mtdowling@gmail.com",
+ "homepage": "https://github.com/mtdowling"
+ },
+ {
+ "name": "Jeremy Lindblom",
+ "email": "jeremeamia@gmail.com",
+ "homepage": "https://github.com/jeremeamia"
+ },
+ {
+ "name": "George Mponos",
+ "email": "gmponos@gmail.com",
+ "homepage": "https://github.com/gmponos"
+ },
+ {
+ "name": "Tobias Nyholm",
+ "email": "tobias.nyholm@gmail.com",
+ "homepage": "https://github.com/Nyholm"
+ },
+ {
+ "name": "Márk Sági-Kazár",
+ "email": "mark.sagikazar@gmail.com",
+ "homepage": "https://github.com/sagikazarmark"
+ },
+ {
+ "name": "Tobias Schultze",
+ "email": "webmaster@tubo-world.de",
+ "homepage": "https://github.com/Tobion"
+ }
+ ],
+ "description": "Guzzle is a PHP HTTP client library",
+ "keywords": [
+ "client",
+ "curl",
+ "framework",
+ "http",
+ "http client",
+ "psr-18",
+ "psr-7",
+ "rest",
+ "web service"
+ ],
+ "support": {
+ "issues": "https://github.com/guzzle/guzzle/issues",
+ "source": "https://github.com/guzzle/guzzle/tree/7.15.3"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/GrahamCampbell",
+ "type": "github"
+ },
+ {
+ "url": "https://github.com/Nyholm",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/guzzle",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2026-08-05T19:48:21+00:00"
+ },
+ {
+ "name": "guzzlehttp/promises",
+ "version": "2.5.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/guzzle/promises.git",
+ "reference": "2823687acff28b2dbe67b2508a6b300e2c3fa4ce"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/guzzle/promises/zipball/2823687acff28b2dbe67b2508a6b300e2c3fa4ce",
+ "reference": "2823687acff28b2dbe67b2508a6b300e2c3fa4ce",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^7.2.5 || ^8.0",
+ "symfony/deprecation-contracts": "^2.5 || ^3.0"
+ },
+ "require-dev": {
+ "bamarni/composer-bin-plugin": "^1.8.2",
+ "phpunit/phpunit": "^8.5.52 || ^9.6.34"
+ },
+ "type": "library",
+ "extra": {
+ "bamarni-bin": {
+ "bin-links": true,
+ "forward-command": false
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "GuzzleHttp\\Promise\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Graham Campbell",
+ "email": "hello@gjcampbell.co.uk",
+ "homepage": "https://github.com/GrahamCampbell"
+ },
+ {
+ "name": "Michael Dowling",
+ "email": "mtdowling@gmail.com",
+ "homepage": "https://github.com/mtdowling"
+ },
+ {
+ "name": "Tobias Nyholm",
+ "email": "tobias.nyholm@gmail.com",
+ "homepage": "https://github.com/Nyholm"
+ },
+ {
+ "name": "Tobias Schultze",
+ "email": "webmaster@tubo-world.de",
+ "homepage": "https://github.com/Tobion"
+ }
+ ],
+ "description": "Guzzle promises library",
+ "keywords": [
+ "promise"
+ ],
+ "support": {
+ "issues": "https://github.com/guzzle/promises/issues",
+ "source": "https://github.com/guzzle/promises/tree/2.5.2"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/GrahamCampbell",
+ "type": "github"
+ },
+ {
+ "url": "https://github.com/Nyholm",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/promises",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2026-08-05T19:30:54+00:00"
+ },
+ {
+ "name": "guzzlehttp/psr7",
+ "version": "2.13.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/guzzle/psr7.git",
+ "reference": "dad89620b7a6edb60c15858442eb2e408b45d8f4"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/guzzle/psr7/zipball/dad89620b7a6edb60c15858442eb2e408b45d8f4",
+ "reference": "dad89620b7a6edb60c15858442eb2e408b45d8f4",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^7.2.5 || ^8.0",
+ "psr/http-factory": "^1.0",
+ "psr/http-message": "^1.1 || ^2.0",
+ "ralouphie/getallheaders": "^3.0",
+ "symfony/deprecation-contracts": "^2.5 || ^3.0",
+ "symfony/polyfill-php80": "^1.25"
+ },
+ "provide": {
+ "psr/http-factory-implementation": "1.0",
+ "psr/http-message-implementation": "1.0"
+ },
+ "require-dev": {
+ "bamarni/composer-bin-plugin": "^1.8.2",
+ "http-interop/http-factory-tests": "1.1.0",
+ "jshttp/mime-db": "1.54.0.1",
+ "phpunit/phpunit": "^8.5.52 || ^9.6.34"
+ },
+ "suggest": {
+ "laminas/laminas-httphandlerrunner": "Emit PSR-7 responses"
+ },
+ "type": "library",
+ "extra": {
+ "bamarni-bin": {
+ "bin-links": true,
+ "forward-command": false
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "GuzzleHttp\\Psr7\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Graham Campbell",
+ "email": "hello@gjcampbell.co.uk",
+ "homepage": "https://github.com/GrahamCampbell"
+ },
+ {
+ "name": "Michael Dowling",
+ "email": "mtdowling@gmail.com",
+ "homepage": "https://github.com/mtdowling"
+ },
+ {
+ "name": "George Mponos",
+ "email": "gmponos@gmail.com",
+ "homepage": "https://github.com/gmponos"
+ },
+ {
+ "name": "Tobias Nyholm",
+ "email": "tobias.nyholm@gmail.com",
+ "homepage": "https://github.com/Nyholm"
+ },
+ {
+ "name": "Márk Sági-Kazár",
+ "email": "mark.sagikazar@gmail.com",
+ "homepage": "https://github.com/sagikazarmark"
+ },
+ {
+ "name": "Tobias Schultze",
+ "email": "webmaster@tubo-world.de",
+ "homepage": "https://github.com/Tobion"
+ },
+ {
+ "name": "Márk Sági-Kazár",
+ "email": "mark.sagikazar@gmail.com",
+ "homepage": "https://sagikazarmark.hu"
+ }
+ ],
+ "description": "PSR-7 message implementation that also provides common utility methods",
+ "keywords": [
+ "http",
+ "message",
+ "psr-7",
+ "request",
+ "response",
+ "stream",
+ "uri",
+ "url"
+ ],
+ "support": {
+ "issues": "https://github.com/guzzle/psr7/issues",
+ "source": "https://github.com/guzzle/psr7/tree/2.13.0"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/GrahamCampbell",
+ "type": "github"
+ },
+ {
+ "url": "https://github.com/Nyholm",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/psr7",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2026-07-16T22:23:49+00:00"
+ },
+ {
+ "name": "guzzlehttp/uri-template",
+ "version": "v1.0.10",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/guzzle/uri-template.git",
+ "reference": "f6c24c21f42b990e9a58912b332d0874df6ba839"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/guzzle/uri-template/zipball/f6c24c21f42b990e9a58912b332d0874df6ba839",
+ "reference": "f6c24c21f42b990e9a58912b332d0874df6ba839",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^7.2.5 || ^8.0",
+ "symfony/polyfill-php80": "^1.25"
+ },
+ "require-dev": {
+ "bamarni/composer-bin-plugin": "^1.8.2",
+ "phpunit/phpunit": "^8.5.52 || ^9.6.34",
+ "uri-template/tests": "1.0.0"
+ },
+ "type": "library",
+ "extra": {
+ "bamarni-bin": {
+ "bin-links": true,
+ "forward-command": false
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "GuzzleHttp\\UriTemplate\\": "src"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Graham Campbell",
+ "email": "hello@gjcampbell.co.uk",
+ "homepage": "https://github.com/GrahamCampbell"
+ },
+ {
+ "name": "Michael Dowling",
+ "email": "mtdowling@gmail.com",
+ "homepage": "https://github.com/mtdowling"
+ },
+ {
+ "name": "George Mponos",
+ "email": "gmponos@gmail.com",
+ "homepage": "https://github.com/gmponos"
+ },
+ {
+ "name": "Tobias Nyholm",
+ "email": "tobias.nyholm@gmail.com",
+ "homepage": "https://github.com/Nyholm"
+ }
+ ],
+ "description": "A polyfill class for uri_template of PHP",
+ "keywords": [
+ "guzzlehttp",
+ "uri-template"
+ ],
+ "support": {
+ "issues": "https://github.com/guzzle/uri-template/issues",
+ "source": "https://github.com/guzzle/uri-template/tree/v1.0.10"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/GrahamCampbell",
+ "type": "github"
+ },
+ {
+ "url": "https://github.com/Nyholm",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/uri-template",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2026-07-17T13:53:03+00:00"
+ },
+ {
+ "name": "jean85/pretty-package-versions",
+ "version": "2.1.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/Jean85/pretty-package-versions.git",
+ "reference": "4d7aa5dab42e2a76d99559706022885de0e18e1a"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/Jean85/pretty-package-versions/zipball/4d7aa5dab42e2a76d99559706022885de0e18e1a",
+ "reference": "4d7aa5dab42e2a76d99559706022885de0e18e1a",
+ "shasum": ""
+ },
+ "require": {
+ "composer-runtime-api": "^2.1.0",
+ "php": "^7.4|^8.0"
+ },
+ "require-dev": {
+ "friendsofphp/php-cs-fixer": "^3.2",
+ "jean85/composer-provided-replaced-stub-package": "^1.0",
+ "phpstan/phpstan": "^2.0",
+ "phpunit/phpunit": "^7.5|^8.5|^9.6",
+ "rector/rector": "^2.0",
+ "vimeo/psalm": "^4.3 || ^5.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Jean85\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Alessandro Lai",
+ "email": "alessandro.lai85@gmail.com"
+ }
+ ],
+ "description": "A library to get pretty versions strings of installed dependencies",
+ "keywords": [
+ "composer",
+ "package",
+ "release",
+ "versions"
+ ],
+ "support": {
+ "issues": "https://github.com/Jean85/pretty-package-versions/issues",
+ "source": "https://github.com/Jean85/pretty-package-versions/tree/2.1.1"
+ },
+ "time": "2025-03-19T14:43:43+00:00"
+ },
+ {
+ "name": "laravel/framework",
+ "version": "v13.24.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/laravel/framework.git",
+ "reference": "6d481710375d2aa67656922ef760cdd2b18bcfe0"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/laravel/framework/zipball/6d481710375d2aa67656922ef760cdd2b18bcfe0",
+ "reference": "6d481710375d2aa67656922ef760cdd2b18bcfe0",
+ "shasum": ""
+ },
+ "require": {
+ "brick/math": "^0.14.2 || ^0.15 || ^0.16 || ^0.17 || ^0.18",
+ "composer-runtime-api": "^2.2",
+ "doctrine/inflector": "^2.0.5",
+ "dragonmantank/cron-expression": "^3.4",
+ "egulias/email-validator": "^4.0",
+ "ext-ctype": "*",
+ "ext-filter": "*",
+ "ext-hash": "*",
+ "ext-mbstring": "*",
+ "ext-openssl": "*",
+ "ext-session": "*",
+ "ext-tokenizer": "*",
+ "fruitcake/php-cors": "^1.3",
+ "guzzlehttp/guzzle": "^7.8.2",
+ "guzzlehttp/promises": "^2.0.3",
+ "guzzlehttp/uri-template": "^1.0",
+ "laravel/prompts": "^0.3.11",
+ "laravel/serializable-closure": "^2.0.10",
+ "league/commonmark": "^2.8.1",
+ "league/flysystem": "^3.25.1",
+ "league/flysystem-local": "^3.25.1",
+ "league/uri": "^7.5.1",
+ "monolog/monolog": "^3.10",
+ "nesbot/carbon": "^3.8.4",
+ "nunomaduro/termwind": "^2.0",
+ "php": "^8.3",
+ "psr/container": "^1.1.1 || ^2.0.1",
+ "psr/log": "^1.0 || ^2.0 || ^3.0",
+ "psr/simple-cache": "^1.0 || ^2.0 || ^3.0",
+ "ramsey/uuid": "^4.7",
+ "symfony/console": "^7.4.0 || ^8.0.0",
+ "symfony/error-handler": "^7.4.0 || ^8.0.0",
+ "symfony/finder": "^7.4.0 || ^8.0.0",
+ "symfony/http-foundation": "^7.4.0 || ^8.0.0",
+ "symfony/http-kernel": "^7.4.0 || ^8.0.0",
+ "symfony/mailer": "^7.4.0 || ^8.0.0",
+ "symfony/mime": "^7.4.0 || ^8.0.0",
+ "symfony/polyfill-php84": "^1.36",
+ "symfony/polyfill-php85": "^1.36",
+ "symfony/polyfill-php86": "^1.36",
+ "symfony/process": "^7.4.5 || ^8.0.5",
+ "symfony/routing": "^7.4.0 || ^8.0.0",
+ "symfony/uid": "^7.4.0 || ^8.0.0",
+ "symfony/var-dumper": "^7.4.0 || ^8.0.0",
+ "tijsverkoyen/css-to-inline-styles": "^2.2.5",
+ "vlucas/phpdotenv": "^5.6.1",
+ "voku/portable-ascii": "^2.0.2"
+ },
+ "conflict": {
+ "tightenco/collect": "<5.5.33"
+ },
+ "provide": {
+ "psr/container-implementation": "1.1 || 2.0",
+ "psr/log-implementation": "1.0 || 2.0 || 3.0",
+ "psr/simple-cache-implementation": "1.0 || 2.0 || 3.0"
+ },
+ "replace": {
+ "illuminate/auth": "self.version",
+ "illuminate/broadcasting": "self.version",
+ "illuminate/bus": "self.version",
+ "illuminate/cache": "self.version",
+ "illuminate/collections": "self.version",
+ "illuminate/concurrency": "self.version",
+ "illuminate/conditionable": "self.version",
+ "illuminate/config": "self.version",
+ "illuminate/console": "self.version",
+ "illuminate/container": "self.version",
+ "illuminate/contracts": "self.version",
+ "illuminate/cookie": "self.version",
+ "illuminate/database": "self.version",
+ "illuminate/encryption": "self.version",
+ "illuminate/events": "self.version",
+ "illuminate/filesystem": "self.version",
+ "illuminate/hashing": "self.version",
+ "illuminate/http": "self.version",
+ "illuminate/image": "self.version",
+ "illuminate/json-schema": "self.version",
+ "illuminate/log": "self.version",
+ "illuminate/macroable": "self.version",
+ "illuminate/mail": "self.version",
+ "illuminate/notifications": "self.version",
+ "illuminate/pagination": "self.version",
+ "illuminate/pipeline": "self.version",
+ "illuminate/process": "self.version",
+ "illuminate/queue": "self.version",
+ "illuminate/redis": "self.version",
+ "illuminate/reflection": "self.version",
+ "illuminate/routing": "self.version",
+ "illuminate/session": "self.version",
+ "illuminate/support": "self.version",
+ "illuminate/testing": "self.version",
+ "illuminate/translation": "self.version",
+ "illuminate/validation": "self.version",
+ "illuminate/view": "self.version",
+ "spatie/once": "*"
+ },
+ "require-dev": {
+ "ably/ably-php": "^1.0",
+ "aws/aws-sdk-php": "^3.322.9",
+ "ext-gmp": "*",
+ "fakerphp/faker": "^1.24",
+ "guzzlehttp/psr7": "^2.9",
+ "intervention/image": "^4.0",
+ "laravel/pint": "^1.18",
+ "league/flysystem-aws-s3-v3": "^3.25.1",
+ "league/flysystem-ftp": "^3.25.1",
+ "league/flysystem-path-prefixing": "^3.25.1",
+ "league/flysystem-read-only": "^3.25.1",
+ "league/flysystem-sftp-v3": "^3.25.1",
+ "mockery/mockery": "^1.6.10",
+ "opis/json-schema": "^2.4.1",
+ "orchestra/testbench-core": "^11.0.0",
+ "pda/pheanstalk": "^7.0.0 || ^8.0.0",
+ "php-http/discovery": "^1.15",
+ "phpstan/phpstan": "^2.0",
+ "phpunit/phpunit": "^11.5.50 || ^12.5.8 || ^13.0.3",
+ "predis/predis": "^2.3 || ^3.0",
+ "rector/rector": "^2.3",
+ "resend/resend-php": "^1.0",
+ "symfony/cache": "^7.4.0 || ^8.0.0",
+ "symfony/http-client": "^7.4.0 || ^8.0.0",
+ "symfony/psr-http-message-bridge": "^7.4.0 || ^8.0.0",
+ "symfony/translation": "^7.4.0 || ^8.0.0"
+ },
+ "suggest": {
+ "ably/ably-php": "Required to use the Ably broadcast driver (^1.0).",
+ "aws/aws-sdk-php": "Required to use the SQS queue driver, DynamoDb failed job storage, and SES mail driver (^3.322.9).",
+ "brianium/paratest": "Required to run tests in parallel (^7.0 || ^8.0).",
+ "ext-apcu": "Required to use the APC cache driver.",
+ "ext-fileinfo": "Required to use the Filesystem class.",
+ "ext-ftp": "Required to use the Flysystem FTP driver.",
+ "ext-gd": "Required to use Illuminate\\Http\\Testing\\FileFactory::image().",
+ "ext-memcached": "Required to use the memcache cache driver.",
+ "ext-pcntl": "Required to use all features of the queue worker and console signal trapping.",
+ "ext-pdo": "Required to use all database features.",
+ "ext-posix": "Required to use all features of the queue worker.",
+ "ext-redis": "Required to use the Redis cache and queue drivers (^4.0 || ^5.0 || ^6.0).",
+ "fakerphp/faker": "Required to generate fake data using the fake() helper (^1.23).",
+ "filp/whoops": "Required for friendly error pages in development (^2.14.3).",
+ "intervention/image": "Required to use the image processing features (^4.0).",
+ "laravel/tinker": "Required to use the tinker console command (^2.0).",
+ "league/flysystem-aws-s3-v3": "Required to use the Flysystem S3 driver (^3.25.1).",
+ "league/flysystem-ftp": "Required to use the Flysystem FTP driver (^3.25.1).",
+ "league/flysystem-path-prefixing": "Required to use the scoped driver (^3.25.1).",
+ "league/flysystem-read-only": "Required to use read-only disks (^3.25.1)",
+ "league/flysystem-sftp-v3": "Required to use the Flysystem SFTP driver (^3.25.1).",
+ "mockery/mockery": "Required to use mocking (^1.6).",
+ "pda/pheanstalk": "Required to use the beanstalk queue driver (^7.0 || ^8.0).",
+ "php-http/discovery": "Required to use PSR-7 bridging features (^1.15).",
+ "phpunit/phpunit": "Required to use assertions and run tests (^11.5.50 || ^12.5.8 || ^13.0.3).",
+ "predis/predis": "Required to use the predis connector (^2.3 || ^3.0).",
+ "psr/http-message": "Required to allow Storage::put to accept a StreamInterface (^1.0).",
+ "pusher/pusher-php-server": "Required to use the Pusher broadcast driver (^6.0 || ^7.0).",
+ "resend/resend-php": "Required to enable support for the Resend mail transport (^0.10.0 || ^1.0).",
+ "spatie/fork": "Required to use the 'fork' concurrency driver (^1.2).",
+ "symfony/cache": "Required to PSR-6 cache bridge (^7.4 || ^8.0).",
+ "symfony/filesystem": "Required to enable support for relative symbolic links (^7.4 || ^8.0).",
+ "symfony/http-client": "Required to enable support for the Symfony API mail transports (^7.4 || ^8.0).",
+ "symfony/mailgun-mailer": "Required to enable support for the Mailgun mail transport (^7.4 || ^8.0).",
+ "symfony/postmark-mailer": "Required to enable support for the Postmark mail transport (^7.4 || ^8.0).",
+ "symfony/psr-http-message-bridge": "Required to use PSR-7 bridging features (^7.4 || ^8.0)."
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "13.0.x-dev"
+ }
+ },
+ "autoload": {
+ "files": [
+ "src/Illuminate/Collections/functions.php",
+ "src/Illuminate/Collections/helpers.php",
+ "src/Illuminate/Events/functions.php",
+ "src/Illuminate/Filesystem/functions.php",
+ "src/Illuminate/Foundation/helpers.php",
+ "src/Illuminate/Log/functions.php",
+ "src/Illuminate/Reflection/helpers.php",
+ "src/Illuminate/Support/functions.php",
+ "src/Illuminate/Support/helpers.php"
+ ],
+ "psr-4": {
+ "Illuminate\\": "src/Illuminate/",
+ "Illuminate\\Support\\": [
+ "src/Illuminate/Macroable/",
+ "src/Illuminate/Collections/",
+ "src/Illuminate/Conditionable/",
+ "src/Illuminate/Reflection/"
+ ]
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Taylor Otwell",
+ "email": "taylor@laravel.com"
+ }
+ ],
+ "description": "The Laravel Framework.",
+ "homepage": "https://laravel.com",
+ "keywords": [
+ "framework",
+ "laravel"
+ ],
+ "support": {
+ "issues": "https://github.com/laravel/framework/issues",
+ "source": "https://github.com/laravel/framework"
+ },
+ "time": "2026-08-04T15:54:59+00:00"
+ },
+ {
+ "name": "laravel/prompts",
+ "version": "v0.3.22",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/laravel/prompts.git",
+ "reference": "02b89b39e8972a998db4d5d4ad4719239dd4aee4"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/laravel/prompts/zipball/02b89b39e8972a998db4d5d4ad4719239dd4aee4",
+ "reference": "02b89b39e8972a998db4d5d4ad4719239dd4aee4",
+ "shasum": ""
+ },
+ "require": {
+ "composer-runtime-api": "^2.2",
+ "ext-mbstring": "*",
+ "php": "^8.1",
+ "symfony/console": "^6.2|^7.0|^8.0"
+ },
+ "conflict": {
+ "illuminate/console": ">=10.17.0 <10.25.0",
+ "laravel/framework": ">=10.17.0 <10.25.0"
+ },
+ "require-dev": {
+ "illuminate/collections": "^10.0|^11.0|^12.0|^13.0",
+ "mockery/mockery": "^1.5",
+ "pestphp/pest": "^2.3|^3.4|^4.0",
+ "phpstan/phpstan": "^1.12.28",
+ "phpstan/phpstan-mockery": "^1.1.3"
+ },
+ "suggest": {
+ "ext-pcntl": "Required for the spinner to be animated."
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "0.3.x-dev"
+ }
+ },
+ "autoload": {
+ "files": [
+ "src/helpers.php"
+ ],
+ "psr-4": {
+ "Laravel\\Prompts\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "description": "Add beautiful and user-friendly forms to your command-line applications.",
+ "support": {
+ "issues": "https://github.com/laravel/prompts/issues",
+ "source": "https://github.com/laravel/prompts/tree/v0.3.22"
+ },
+ "time": "2026-08-04T14:50:50+00:00"
+ },
+ {
+ "name": "laravel/sanctum",
+ "version": "v4.3.3",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/laravel/sanctum.git",
+ "reference": "fee27a573d1a013af3721d86153a65e0b11927e6"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/laravel/sanctum/zipball/fee27a573d1a013af3721d86153a65e0b11927e6",
+ "reference": "fee27a573d1a013af3721d86153a65e0b11927e6",
+ "shasum": ""
+ },
+ "require": {
+ "ext-json": "*",
+ "illuminate/console": "^11.0|^12.0|^13.0",
+ "illuminate/contracts": "^11.0|^12.0|^13.0",
+ "illuminate/database": "^11.0|^12.0|^13.0",
+ "illuminate/support": "^11.0|^12.0|^13.0",
+ "php": "^8.2",
+ "symfony/console": "^7.0|^8.0"
+ },
+ "require-dev": {
+ "mockery/mockery": "^1.6",
+ "orchestra/testbench": "^9.15|^10.8|^11.0",
+ "phpstan/phpstan": "^1.10"
+ },
+ "type": "library",
+ "extra": {
+ "laravel": {
+ "providers": [
+ "Laravel\\Sanctum\\SanctumServiceProvider"
+ ]
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Laravel\\Sanctum\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Taylor Otwell",
+ "email": "taylor@laravel.com"
+ }
+ ],
+ "description": "Laravel Sanctum provides a featherweight authentication system for SPAs and simple APIs.",
+ "keywords": [
+ "auth",
+ "laravel",
+ "sanctum"
+ ],
+ "support": {
+ "issues": "https://github.com/laravel/sanctum/issues",
+ "source": "https://github.com/laravel/sanctum"
+ },
+ "time": "2026-06-23T18:26:55+00:00"
+ },
+ {
+ "name": "laravel/serializable-closure",
+ "version": "v2.0.15",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/laravel/serializable-closure.git",
+ "reference": "dccd8bcb851bb03fcc005df650b708b57cc52661"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/laravel/serializable-closure/zipball/dccd8bcb851bb03fcc005df650b708b57cc52661",
+ "reference": "dccd8bcb851bb03fcc005df650b708b57cc52661",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^8.1"
+ },
+ "require-dev": {
+ "illuminate/support": "^10.0|^11.0|^12.0|^13.0",
+ "nesbot/carbon": "^2.67|^3.0",
+ "pestphp/pest": "^2.36|^3.0|^4.0",
+ "phpstan/phpstan": "^2.0",
+ "symfony/var-dumper": "^6.2.0|^7.0.0|^8.0.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.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": "2026-07-21T16:49:22+00:00"
+ },
+ {
+ "name": "league/commonmark",
+ "version": "2.9.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/thephpleague/commonmark.git",
+ "reference": "73cb188c785abfa7a7bec73487148202968274c6"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/thephpleague/commonmark/zipball/73cb188c785abfa7a7bec73487148202968274c6",
+ "reference": "73cb188c785abfa7a7bec73487148202968274c6",
+ "shasum": ""
+ },
+ "require": {
+ "ext-mbstring": "*",
+ "league/config": "^1.1.1",
+ "php": "^7.4 || ^8.0",
+ "psr/event-dispatcher": "^1.0",
+ "symfony/deprecation-contracts": "^2.1 || ^3.0",
+ "symfony/polyfill-php80": "^1.16"
+ },
+ "require-dev": {
+ "cebe/markdown": "^1.0",
+ "commonmark/cmark": "0.31.1",
+ "commonmark/commonmark.js": "0.31.1",
+ "composer/package-versions-deprecated": "^1.8",
+ "embed/embed": "^4.4",
+ "erusev/parsedown": "^1.0",
+ "ext-json": "*",
+ "github/gfm": "0.29.0",
+ "michelf/php-markdown": "^1.4 || ^2.0",
+ "nyholm/psr7": "^1.5",
+ "phpstan/phpstan": "^2.0.0",
+ "phpunit/phpunit": "^9.5.21 || ^10.5.9 || ^11.0.0 || ^12.0.0 || ^13.0.0",
+ "scrutinizer/ocular": "^1.8.1",
+ "symfony/finder": "^5.3 | ^6.0 | ^7.0 || ^8.0",
+ "symfony/process": "^5.4 | ^6.0 | ^7.0 || ^8.0",
+ "symfony/yaml": "^2.3 | ^3.0 | ^4.0 | ^5.0 | ^6.0 | ^7.0 || ^8.0",
+ "unleashedtech/php-coding-standard": "^3.1.1",
+ "vimeo/psalm": "^4.24.0 || ^5.0.0 || ^6.0.0"
+ },
+ "suggest": {
+ "symfony/yaml": "v2.3+ required if using the Front Matter extension"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "2.10-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "League\\CommonMark\\": "src"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Colin O'Dell",
+ "email": "colinodell@gmail.com",
+ "homepage": "https://www.colinodell.com",
+ "role": "Lead Developer"
+ }
+ ],
+ "description": "Highly-extensible PHP Markdown parser which fully supports the CommonMark spec and GitHub-Flavored Markdown (GFM)",
+ "homepage": "https://commonmark.thephpleague.com",
+ "keywords": [
+ "commonmark",
+ "flavored",
+ "gfm",
+ "github",
+ "github-flavored",
+ "markdown",
+ "md",
+ "parser"
+ ],
+ "support": {
+ "docs": "https://commonmark.thephpleague.com/",
+ "forum": "https://github.com/thephpleague/commonmark/discussions",
+ "issues": "https://github.com/thephpleague/commonmark/issues",
+ "rss": "https://github.com/thephpleague/commonmark/releases.atom",
+ "source": "https://github.com/thephpleague/commonmark"
+ },
+ "funding": [
+ {
+ "url": "https://www.colinodell.com/sponsor",
+ "type": "custom"
+ },
+ {
+ "url": "https://www.paypal.me/colinpodell/10.00",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/colinodell",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/league/commonmark",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2026-08-09T14:10:38+00:00"
+ },
+ {
+ "name": "league/config",
+ "version": "v1.2.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/thephpleague/config.git",
+ "reference": "754b3604fb2984c71f4af4a9cbe7b57f346ec1f3"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/thephpleague/config/zipball/754b3604fb2984c71f4af4a9cbe7b57f346ec1f3",
+ "reference": "754b3604fb2984c71f4af4a9cbe7b57f346ec1f3",
+ "shasum": ""
+ },
+ "require": {
+ "dflydev/dot-access-data": "^3.0.1",
+ "nette/schema": "^1.2",
+ "php": "^7.4 || ^8.0"
+ },
+ "require-dev": {
+ "phpstan/phpstan": "^1.8.2",
+ "phpunit/phpunit": "^9.5.5",
+ "scrutinizer/ocular": "^1.8.1",
+ "unleashedtech/php-coding-standard": "^3.1",
+ "vimeo/psalm": "^4.7.3"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "1.2-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "League\\Config\\": "src"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Colin O'Dell",
+ "email": "colinodell@gmail.com",
+ "homepage": "https://www.colinodell.com",
+ "role": "Lead Developer"
+ }
+ ],
+ "description": "Define configuration arrays with strict schemas and access values with dot notation",
+ "homepage": "https://config.thephpleague.com",
+ "keywords": [
+ "array",
+ "config",
+ "configuration",
+ "dot",
+ "dot-access",
+ "nested",
+ "schema"
+ ],
+ "support": {
+ "docs": "https://config.thephpleague.com/",
+ "issues": "https://github.com/thephpleague/config/issues",
+ "rss": "https://github.com/thephpleague/config/releases.atom",
+ "source": "https://github.com/thephpleague/config"
+ },
+ "funding": [
+ {
+ "url": "https://www.colinodell.com/sponsor",
+ "type": "custom"
+ },
+ {
+ "url": "https://www.paypal.me/colinpodell/10.00",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/colinodell",
+ "type": "github"
+ }
+ ],
+ "time": "2022-12-11T20:36:23+00:00"
+ },
+ {
+ "name": "league/flysystem",
+ "version": "3.35.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/thephpleague/flysystem.git",
+ "reference": "b277b5dc3d56650b68904117124e79c851e12376"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/thephpleague/flysystem/zipball/b277b5dc3d56650b68904117124e79c851e12376",
+ "reference": "b277b5dc3d56650b68904117124e79c851e12376",
+ "shasum": ""
+ },
+ "require": {
+ "league/flysystem-local": "^3.0.0",
+ "league/mime-type-detection": "^1.0.0",
+ "php": "^8.0.2"
+ },
+ "conflict": {
+ "async-aws/core": "<1.19.0",
+ "async-aws/s3": "<1.14.0",
+ "aws/aws-sdk-php": "3.209.31 || 3.210.0",
+ "guzzlehttp/guzzle": "<7.0",
+ "guzzlehttp/ringphp": "<1.1.1",
+ "phpseclib/phpseclib": "3.0.15",
+ "symfony/http-client": "<5.2"
+ },
+ "require-dev": {
+ "async-aws/s3": "^1.5 || ^2.0",
+ "async-aws/simple-s3": "^1.1 || ^2.0",
+ "aws/aws-sdk-php": "^3.295.10",
+ "composer/semver": "^3.0",
+ "ext-fileinfo": "*",
+ "ext-ftp": "*",
+ "ext-mongodb": "^1.3|^2",
+ "ext-zip": "*",
+ "friendsofphp/php-cs-fixer": "^3.5",
+ "google/cloud-storage": "^1.23",
+ "guzzlehttp/psr7": "^2.6",
+ "microsoft/azure-storage-blob": "^1.1",
+ "mongodb/mongodb": "^1.2|^2",
+ "phpseclib/phpseclib": "^3.0.36",
+ "phpstan/phpstan": "^1.10",
+ "phpunit/phpunit": "^9.5.11|^10.0",
+ "sabre/dav": "^4.6.0"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "League\\Flysystem\\": "src"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Frank de Jonge",
+ "email": "info@frankdejonge.nl"
+ }
+ ],
+ "description": "File storage abstraction for PHP",
+ "keywords": [
+ "WebDAV",
+ "aws",
+ "cloud",
+ "file",
+ "files",
+ "filesystem",
+ "filesystems",
+ "ftp",
+ "s3",
+ "sftp",
+ "storage"
+ ],
+ "support": {
+ "issues": "https://github.com/thephpleague/flysystem/issues",
+ "source": "https://github.com/thephpleague/flysystem/tree/3.35.2"
+ },
+ "time": "2026-07-06T14:42:07+00:00"
+ },
+ {
+ "name": "league/flysystem-local",
+ "version": "3.31.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/thephpleague/flysystem-local.git",
+ "reference": "2f669db18a4c20c755c2bb7d3a7b0b2340488079"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/thephpleague/flysystem-local/zipball/2f669db18a4c20c755c2bb7d3a7b0b2340488079",
+ "reference": "2f669db18a4c20c755c2bb7d3a7b0b2340488079",
+ "shasum": ""
+ },
+ "require": {
+ "ext-fileinfo": "*",
+ "league/flysystem": "^3.0.0",
+ "league/mime-type-detection": "^1.0.0",
+ "php": "^8.0.2"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "League\\Flysystem\\Local\\": ""
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Frank de Jonge",
+ "email": "info@frankdejonge.nl"
+ }
+ ],
+ "description": "Local filesystem adapter for Flysystem.",
+ "keywords": [
+ "Flysystem",
+ "file",
+ "files",
+ "filesystem",
+ "local"
+ ],
+ "support": {
+ "source": "https://github.com/thephpleague/flysystem-local/tree/3.31.0"
+ },
+ "time": "2026-01-23T15:30:45+00:00"
+ },
+ {
+ "name": "league/mime-type-detection",
+ "version": "1.17.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/thephpleague/mime-type-detection.git",
+ "reference": "f5f47eff7c48ed1003069a2ca67f316fb4021c76"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/thephpleague/mime-type-detection/zipball/f5f47eff7c48ed1003069a2ca67f316fb4021c76",
+ "reference": "f5f47eff7c48ed1003069a2ca67f316fb4021c76",
+ "shasum": ""
+ },
+ "require": {
+ "ext-fileinfo": "*",
+ "php": "^7.4 || ^8.0"
+ },
+ "require-dev": {
+ "friendsofphp/php-cs-fixer": "^3.2",
+ "phpstan/phpstan": "^0.12.68",
+ "phpunit/phpunit": "^8.5.8 || ^9.3 || ^10.0 || ^11.0 || ^12.0"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "League\\MimeTypeDetection\\": "src"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Frank de Jonge",
+ "email": "info@frankdejonge.nl"
+ }
+ ],
+ "description": "Mime-type detection for Flysystem",
+ "support": {
+ "issues": "https://github.com/thephpleague/mime-type-detection/issues",
+ "source": "https://github.com/thephpleague/mime-type-detection/tree/1.17.0"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/frankdejonge",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/league/flysystem",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2026-07-09T11:49:27+00:00"
+ },
+ {
+ "name": "league/uri",
+ "version": "7.8.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/thephpleague/uri.git",
+ "reference": "08cf38e3924d4f56238125547b5720496fac8fd4"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/thephpleague/uri/zipball/08cf38e3924d4f56238125547b5720496fac8fd4",
+ "reference": "08cf38e3924d4f56238125547b5720496fac8fd4",
+ "shasum": ""
+ },
+ "require": {
+ "league/uri-interfaces": "^7.8.1",
+ "php": "^8.1",
+ "psr/http-factory": "^1"
+ },
+ "conflict": {
+ "league/uri-schemes": "^1.0"
+ },
+ "suggest": {
+ "ext-bcmath": "to improve IPV4 host parsing",
+ "ext-dom": "to convert the URI into an HTML anchor tag",
+ "ext-fileinfo": "to create Data URI from file contennts",
+ "ext-gmp": "to improve IPV4 host parsing",
+ "ext-intl": "to handle IDN host with the best performance",
+ "ext-uri": "to use the PHP native URI class",
+ "jeremykendall/php-domain-parser": "to further parse the URI host and resolve its Public Suffix and Top Level Domain",
+ "league/uri-components": "to provide additional tools to manipulate URI objects components",
+ "league/uri-polyfill": "to backport the PHP URI extension for older versions of PHP",
+ "php-64bit": "to improve IPV4 host parsing",
+ "rowbot/url": "to handle URLs using the WHATWG URL Living Standard specification",
+ "symfony/polyfill-intl-idn": "to handle IDN host via the Symfony polyfill if ext-intl is not present"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "7.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "League\\Uri\\": ""
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Ignace Nyamagana Butera",
+ "email": "nyamsprod@gmail.com",
+ "homepage": "https://nyamsprod.com"
+ }
+ ],
+ "description": "URI manipulation library",
+ "homepage": "https://uri.thephpleague.com",
+ "keywords": [
+ "URN",
+ "data-uri",
+ "file-uri",
+ "ftp",
+ "hostname",
+ "http",
+ "https",
+ "middleware",
+ "parse_str",
+ "parse_url",
+ "psr-7",
+ "query-string",
+ "querystring",
+ "rfc2141",
+ "rfc3986",
+ "rfc3987",
+ "rfc6570",
+ "rfc8141",
+ "uri",
+ "uri-template",
+ "url",
+ "ws"
+ ],
+ "support": {
+ "docs": "https://uri.thephpleague.com",
+ "forum": "https://thephpleague.slack.com",
+ "issues": "https://github.com/thephpleague/uri-src/issues",
+ "source": "https://github.com/thephpleague/uri/tree/7.8.1"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sponsors/nyamsprod",
+ "type": "github"
+ }
+ ],
+ "time": "2026-03-15T20:22:25+00:00"
+ },
+ {
+ "name": "league/uri-interfaces",
+ "version": "7.8.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/thephpleague/uri-interfaces.git",
+ "reference": "85d5c77c5d6d3af6c54db4a78246364908f3c928"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/thephpleague/uri-interfaces/zipball/85d5c77c5d6d3af6c54db4a78246364908f3c928",
+ "reference": "85d5c77c5d6d3af6c54db4a78246364908f3c928",
+ "shasum": ""
+ },
+ "require": {
+ "ext-filter": "*",
+ "php": "^8.1",
+ "psr/http-message": "^1.1 || ^2.0"
+ },
+ "suggest": {
+ "ext-bcmath": "to improve IPV4 host parsing",
+ "ext-gmp": "to improve IPV4 host parsing",
+ "ext-intl": "to handle IDN host with the best performance",
+ "php-64bit": "to improve IPV4 host parsing",
+ "rowbot/url": "to handle URLs using the WHATWG URL Living Standard specification",
+ "symfony/polyfill-intl-idn": "to handle IDN host via the Symfony polyfill if ext-intl is not present"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "7.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "League\\Uri\\": ""
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Ignace Nyamagana Butera",
+ "email": "nyamsprod@gmail.com",
+ "homepage": "https://nyamsprod.com"
+ }
+ ],
+ "description": "Common tools for parsing and resolving RFC3987/RFC3986 URI",
+ "homepage": "https://uri.thephpleague.com",
+ "keywords": [
+ "data-uri",
+ "file-uri",
+ "ftp",
+ "hostname",
+ "http",
+ "https",
+ "parse_str",
+ "parse_url",
+ "psr-7",
+ "query-string",
+ "querystring",
+ "rfc3986",
+ "rfc3987",
+ "rfc6570",
+ "uri",
+ "url",
+ "ws"
+ ],
+ "support": {
+ "docs": "https://uri.thephpleague.com",
+ "forum": "https://thephpleague.slack.com",
+ "issues": "https://github.com/thephpleague/uri-src/issues",
+ "source": "https://github.com/thephpleague/uri-interfaces/tree/7.8.1"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sponsors/nyamsprod",
+ "type": "github"
+ }
+ ],
+ "time": "2026-03-08T20:05:35+00:00"
+ },
+ {
+ "name": "monolog/monolog",
+ "version": "3.10.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/Seldaek/monolog.git",
+ "reference": "b321dd6749f0bf7189444158a3ce785cc16d69b0"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/Seldaek/monolog/zipball/b321dd6749f0bf7189444158a3ce785cc16d69b0",
+ "reference": "b321dd6749f0bf7189444158a3ce785cc16d69b0",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.1",
+ "psr/log": "^2.0 || ^3.0"
+ },
+ "provide": {
+ "psr/log-implementation": "3.0.0"
+ },
+ "require-dev": {
+ "aws/aws-sdk-php": "^3.0",
+ "doctrine/couchdb": "~1.0@dev",
+ "elasticsearch/elasticsearch": "^7 || ^8",
+ "ext-json": "*",
+ "graylog2/gelf-php": "^1.4.2 || ^2.0",
+ "guzzlehttp/guzzle": "^7.4.5",
+ "guzzlehttp/psr7": "^2.2",
+ "mongodb/mongodb": "^1.8 || ^2.0",
+ "php-amqplib/php-amqplib": "~2.4 || ^3",
+ "php-console/php-console": "^3.1.8",
+ "phpstan/phpstan": "^2",
+ "phpstan/phpstan-deprecation-rules": "^2",
+ "phpstan/phpstan-strict-rules": "^2",
+ "phpunit/phpunit": "^10.5.17 || ^11.0.7",
+ "predis/predis": "^1.1 || ^2",
+ "rollbar/rollbar": "^4.0",
+ "ruflin/elastica": "^7 || ^8",
+ "symfony/mailer": "^5.4 || ^6",
+ "symfony/mime": "^5.4 || ^6"
+ },
+ "suggest": {
+ "aws/aws-sdk-php": "Allow sending log messages to AWS services like DynamoDB",
+ "doctrine/couchdb": "Allow sending log messages to a CouchDB server",
+ "elasticsearch/elasticsearch": "Allow sending log messages to an Elasticsearch server via official client",
+ "ext-amqp": "Allow sending log messages to an AMQP server (1.0+ required)",
+ "ext-curl": "Required to send log messages using the IFTTTHandler, the LogglyHandler, the SendGridHandler, the SlackWebhookHandler or the TelegramBotHandler",
+ "ext-mbstring": "Allow to work properly with unicode symbols",
+ "ext-mongodb": "Allow sending log messages to a MongoDB server (via driver)",
+ "ext-openssl": "Required to send log messages using SSL",
+ "ext-sockets": "Allow sending log messages to a Syslog server (via UDP driver)",
+ "graylog2/gelf-php": "Allow sending log messages to a GrayLog2 server",
+ "mongodb/mongodb": "Allow sending log messages to a MongoDB server (via library)",
+ "php-amqplib/php-amqplib": "Allow sending log messages to an AMQP server using php-amqplib",
+ "rollbar/rollbar": "Allow sending log messages to Rollbar",
+ "ruflin/elastica": "Allow sending log messages to an Elastic Search server"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "3.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Monolog\\": "src/Monolog"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Jordi Boggiano",
+ "email": "j.boggiano@seld.be",
+ "homepage": "https://seld.be"
+ }
+ ],
+ "description": "Sends your logs to files, sockets, inboxes, databases and various web services",
+ "homepage": "https://github.com/Seldaek/monolog",
+ "keywords": [
+ "log",
+ "logging",
+ "psr-3"
+ ],
+ "support": {
+ "issues": "https://github.com/Seldaek/monolog/issues",
+ "source": "https://github.com/Seldaek/monolog/tree/3.10.0"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/Seldaek",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/monolog/monolog",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2026-01-02T08:56:05+00:00"
+ },
+ {
+ "name": "nesbot/carbon",
+ "version": "3.13.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/CarbonPHP/carbon.git",
+ "reference": "a1c54919f5fff9800cd03c32bd01defd5a4061cb"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/CarbonPHP/carbon/zipball/a1c54919f5fff9800cd03c32bd01defd5a4061cb",
+ "reference": "a1c54919f5fff9800cd03c32bd01defd5a4061cb",
+ "shasum": ""
+ },
+ "require": {
+ "carbonphp/carbon-doctrine-types": "<100.0",
+ "ext-json": "*",
+ "php": "^8.1",
+ "psr/clock": "^1.0",
+ "symfony/clock": "^6.3.12 || ^7.0 || ^8.0",
+ "symfony/polyfill-mbstring": "^1.0",
+ "symfony/translation": "^4.4.18 || ^5.2.1 || ^6.0 || ^7.0 || ^8.0"
+ },
+ "provide": {
+ "psr/clock-implementation": "1.0"
+ },
+ "require-dev": {
+ "doctrine/dbal": "^3.6.3 || ^4.0",
+ "doctrine/orm": "^2.15.2 || ^3.0",
+ "friendsofphp/php-cs-fixer": "^v3.87.1",
+ "kylekatarnls/multi-tester": "^2.5.3",
+ "phpmd/phpmd": "^2.15.0",
+ "phpstan/extension-installer": "^1.4.3",
+ "phpstan/phpstan": "^2.1.22",
+ "phpunit/phpunit": "^10.5.53",
+ "squizlabs/php_codesniffer": "^3.13.4 || ^4.0.0"
+ },
+ "bin": [
+ "bin/carbon"
+ ],
+ "type": "library",
+ "extra": {
+ "laravel": {
+ "providers": [
+ "Carbon\\Laravel\\ServiceProvider"
+ ]
+ },
+ "phpstan": {
+ "includes": [
+ "extension.neon"
+ ]
+ },
+ "branch-alias": {
+ "dev-2.x": "2.x-dev",
+ "dev-master": "3.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Carbon\\": "src/Carbon/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Brian Nesbitt",
+ "email": "brian@nesbot.com",
+ "homepage": "https://markido.com"
+ },
+ {
+ "name": "kylekatarnls",
+ "homepage": "https://github.com/kylekatarnls"
+ }
+ ],
+ "description": "An API extension for DateTime that supports 281 different languages.",
+ "homepage": "https://carbonphp.github.io/carbon/",
+ "keywords": [
+ "date",
+ "datetime",
+ "time"
+ ],
+ "support": {
+ "docs": "https://carbonphp.github.io/carbon/guide/getting-started/introduction.html",
+ "issues": "https://github.com/CarbonPHP/carbon/issues",
+ "source": "https://github.com/CarbonPHP/carbon"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sponsors/kylekatarnls",
+ "type": "github"
+ },
+ {
+ "url": "https://opencollective.com/Carbon#sponsor",
+ "type": "opencollective"
+ },
+ {
+ "url": "https://tidelift.com/subscription/pkg/packagist-nesbot-carbon?utm_source=packagist-nesbot-carbon&utm_medium=referral&utm_campaign=readme",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2026-08-08T11:40:35+00:00"
+ },
+ {
+ "name": "nette/schema",
+ "version": "v1.3.5",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/nette/schema.git",
+ "reference": "f0ab1a3cda782dbc5da270d28545236aa80c4002"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/nette/schema/zipball/f0ab1a3cda782dbc5da270d28545236aa80c4002",
+ "reference": "f0ab1a3cda782dbc5da270d28545236aa80c4002",
+ "shasum": ""
+ },
+ "require": {
+ "nette/utils": "^4.0",
+ "php": "8.1 - 8.5"
+ },
+ "require-dev": {
+ "nette/phpstan-rules": "^1.0",
+ "nette/tester": "^2.6",
+ "phpstan/extension-installer": "^1.4@stable",
+ "phpstan/phpstan": "^2.1.39@stable",
+ "tracy/tracy": "^2.8"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.3-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Nette\\": "src"
+ },
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause",
+ "GPL-2.0-only",
+ "GPL-3.0-only"
+ ],
+ "authors": [
+ {
+ "name": "David Grudl",
+ "homepage": "https://davidgrudl.com"
+ },
+ {
+ "name": "Nette Community",
+ "homepage": "https://nette.org/contributors"
+ }
+ ],
+ "description": "📐 Nette Schema: validating data structures against a given Schema.",
+ "homepage": "https://nette.org",
+ "keywords": [
+ "config",
+ "nette"
+ ],
+ "support": {
+ "issues": "https://github.com/nette/schema/issues",
+ "source": "https://github.com/nette/schema/tree/v1.3.5"
+ },
+ "time": "2026-02-23T03:47:12+00:00"
+ },
+ {
+ "name": "nette/utils",
+ "version": "v4.1.5",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/nette/utils.git",
+ "reference": "b043439dbdf954e6c28b5ea7e34b0100f83165e0"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/nette/utils/zipball/b043439dbdf954e6c28b5ea7e34b0100f83165e0",
+ "reference": "b043439dbdf954e6c28b5ea7e34b0100f83165e0",
+ "shasum": ""
+ },
+ "require": {
+ "php": "8.2 - 8.5"
+ },
+ "conflict": {
+ "nette/finder": "<3",
+ "nette/schema": "<1.2.2"
+ },
+ "require-dev": {
+ "jetbrains/phpstorm-attributes": "^1.2",
+ "nette/phpstan-rules": "^1.0",
+ "nette/tester": "^2.5",
+ "phpstan/extension-installer": "^1.4@stable",
+ "phpstan/phpstan": "^2.1@stable",
+ "tracy/tracy": "^2.9"
+ },
+ "suggest": {
+ "ext-gd": "to use Image",
+ "ext-iconv": "to use Strings::chr(), ord() and reverse()",
+ "ext-intl": "to use Strings::webalize(), toAscii(), normalize() and compare()",
+ "ext-json": "to use Nette\\Utils\\Json",
+ "ext-mbstring": "to use Strings::lower() etc...",
+ "ext-tokenizer": "to use Nette\\Utils\\Reflection::getUseStatements()"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "4.1-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Nette\\": "src"
+ },
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause",
+ "GPL-2.0-only",
+ "GPL-3.0-only"
+ ],
+ "authors": [
+ {
+ "name": "David Grudl",
+ "homepage": "https://davidgrudl.com"
+ },
+ {
+ "name": "Nette Community",
+ "homepage": "https://nette.org/contributors"
+ }
+ ],
+ "description": "🛠 Nette Utils: lightweight utilities for string & array manipulation, image handling, safe JSON encoding/decoding, validation, slug or strong password generating etc.",
+ "homepage": "https://nette.org",
+ "keywords": [
+ "array",
+ "core",
+ "datetime",
+ "images",
+ "json",
+ "nette",
+ "paginator",
+ "password",
+ "slugify",
+ "string",
+ "unicode",
+ "utf-8",
+ "utility",
+ "validation"
+ ],
+ "support": {
+ "issues": "https://github.com/nette/utils/issues",
+ "source": "https://github.com/nette/utils/tree/v4.1.5"
+ },
+ "time": "2026-07-17T23:02:45+00:00"
+ },
+ {
+ "name": "nunomaduro/termwind",
+ "version": "v2.4.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/nunomaduro/termwind.git",
+ "reference": "712a31b768f5daea284c2169a7d227031001b9a8"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/nunomaduro/termwind/zipball/712a31b768f5daea284c2169a7d227031001b9a8",
+ "reference": "712a31b768f5daea284c2169a7d227031001b9a8",
+ "shasum": ""
+ },
+ "require": {
+ "ext-mbstring": "*",
+ "php": "^8.2",
+ "symfony/console": "^7.4.4 || ^8.0.4"
+ },
+ "require-dev": {
+ "illuminate/console": "^11.47.0",
+ "laravel/pint": "^1.27.1",
+ "mockery/mockery": "^1.6.12",
+ "pestphp/pest": "^2.36.0 || ^3.8.4 || ^4.3.2",
+ "phpstan/phpstan": "^1.12.32",
+ "phpstan/phpstan-strict-rules": "^1.6.2",
+ "symfony/var-dumper": "^7.3.5 || ^8.0.4",
+ "thecodingmachine/phpstan-strict-rules": "^1.0.0"
+ },
+ "type": "library",
+ "extra": {
+ "laravel": {
+ "providers": [
+ "Termwind\\Laravel\\TermwindServiceProvider"
+ ]
+ },
+ "branch-alias": {
+ "dev-2.x": "2.x-dev"
+ }
+ },
+ "autoload": {
+ "files": [
+ "src/Functions.php"
+ ],
+ "psr-4": {
+ "Termwind\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Nuno Maduro",
+ "email": "enunomaduro@gmail.com"
+ }
+ ],
+ "description": "It's like Tailwind CSS, but for the console.",
+ "keywords": [
+ "cli",
+ "console",
+ "css",
+ "package",
+ "php",
+ "style"
+ ],
+ "support": {
+ "issues": "https://github.com/nunomaduro/termwind/issues",
+ "source": "https://github.com/nunomaduro/termwind/tree/v2.4.0"
+ },
+ "funding": [
+ {
+ "url": "https://www.paypal.com/paypalme/enunomaduro",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/nunomaduro",
+ "type": "github"
+ },
+ {
+ "url": "https://github.com/xiCO2k",
+ "type": "github"
+ }
+ ],
+ "time": "2026-02-16T23:10:27+00:00"
+ },
+ {
+ "name": "nyholm/psr7",
+ "version": "1.8.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/Nyholm/psr7.git",
+ "reference": "a71f2b11690f4b24d099d6b16690a90ae14fc6f3"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/Nyholm/psr7/zipball/a71f2b11690f4b24d099d6b16690a90ae14fc6f3",
+ "reference": "a71f2b11690f4b24d099d6b16690a90ae14fc6f3",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.2",
+ "psr/http-factory": "^1.0",
+ "psr/http-message": "^1.1 || ^2.0"
+ },
+ "provide": {
+ "php-http/message-factory-implementation": "1.0",
+ "psr/http-factory-implementation": "1.0",
+ "psr/http-message-implementation": "1.0"
+ },
+ "require-dev": {
+ "http-interop/http-factory-tests": "^0.9",
+ "php-http/message-factory": "^1.0",
+ "php-http/psr7-integration-tests": "^1.0",
+ "phpunit/phpunit": "^7.5 || ^8.5 || ^9.4",
+ "symfony/error-handler": "^4.4"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.8-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Nyholm\\Psr7\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Tobias Nyholm",
+ "email": "tobias.nyholm@gmail.com"
+ },
+ {
+ "name": "Martijn van der Ven",
+ "email": "martijn@vanderven.se"
+ }
+ ],
+ "description": "A fast PHP7 implementation of PSR-7",
+ "homepage": "https://tnyholm.se",
+ "keywords": [
+ "psr-17",
+ "psr-7"
+ ],
+ "support": {
+ "issues": "https://github.com/Nyholm/psr7/issues",
+ "source": "https://github.com/Nyholm/psr7/tree/1.8.2"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/Zegnat",
+ "type": "github"
+ },
+ {
+ "url": "https://github.com/nyholm",
+ "type": "github"
+ }
+ ],
+ "time": "2024-09-09T07:06:30+00:00"
+ },
+ {
+ "name": "phpoption/phpoption",
+ "version": "1.9.5",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/schmittjoh/php-option.git",
+ "reference": "75365b91986c2405cf5e1e012c5595cd487a98be"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/schmittjoh/php-option/zipball/75365b91986c2405cf5e1e012c5595cd487a98be",
+ "reference": "75365b91986c2405cf5e1e012c5595cd487a98be",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^7.2.5 || ^8.0"
+ },
+ "require-dev": {
+ "bamarni/composer-bin-plugin": "^1.8.2",
+ "phpunit/phpunit": "^8.5.44 || ^9.6.25 || ^10.5.53 || ^11.5.34"
+ },
+ "type": "library",
+ "extra": {
+ "bamarni-bin": {
+ "bin-links": true,
+ "forward-command": false
+ },
+ "branch-alias": {
+ "dev-master": "1.9-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "PhpOption\\": "src/PhpOption/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "Apache-2.0"
+ ],
+ "authors": [
+ {
+ "name": "Johannes M. Schmitt",
+ "email": "schmittjoh@gmail.com",
+ "homepage": "https://github.com/schmittjoh"
+ },
+ {
+ "name": "Graham Campbell",
+ "email": "hello@gjcampbell.co.uk",
+ "homepage": "https://github.com/GrahamCampbell"
+ }
+ ],
+ "description": "Option Type for PHP",
+ "keywords": [
+ "language",
+ "option",
+ "php",
+ "type"
+ ],
+ "support": {
+ "issues": "https://github.com/schmittjoh/php-option/issues",
+ "source": "https://github.com/schmittjoh/php-option/tree/1.9.5"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/GrahamCampbell",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/phpoption/phpoption",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2025-12-27T19:41:33+00:00"
+ },
+ {
+ "name": "phpstan/phpstan",
+ "version": "2.2.8",
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/phpstan/phpstan/zipball/e285254e60f33c21902efef4a926ca0987c06804",
+ "reference": "e285254e60f33c21902efef4a926ca0987c06804",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^7.4|^8.0"
+ },
+ "conflict": {
+ "phpstan/phpstan-shim": "*"
+ },
+ "bin": [
+ "phpstan",
+ "phpstan.phar"
+ ],
+ "type": "library",
+ "autoload": {
+ "files": [
+ "bootstrap.php"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Ondřej Mirtes"
+ },
+ {
+ "name": "Markus Staab"
+ },
+ {
+ "name": "Vincent Langlet"
+ }
+ ],
+ "description": "PHPStan - PHP Static Analysis Tool",
+ "keywords": [
+ "dev",
+ "static analysis"
+ ],
+ "support": {
+ "docs": "https://phpstan.org/user-guide/getting-started",
+ "forum": "https://github.com/phpstan/phpstan/discussions",
+ "issues": "https://github.com/phpstan/phpstan/issues",
+ "security": "https://github.com/phpstan/phpstan/security/policy",
+ "source": "https://github.com/phpstan/phpstan-src"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/ondrejmirtes",
+ "type": "github"
+ },
+ {
+ "url": "https://github.com/phpstan",
+ "type": "github"
+ }
+ ],
+ "time": "2026-08-04T22:21:45+00:00"
+ },
+ {
+ "name": "psr/clock",
+ "version": "1.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/php-fig/clock.git",
+ "reference": "e41a24703d4560fd0acb709162f73b8adfc3aa0d"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/php-fig/clock/zipball/e41a24703d4560fd0acb709162f73b8adfc3aa0d",
+ "reference": "e41a24703d4560fd0acb709162f73b8adfc3aa0d",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^7.0 || ^8.0"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Psr\\Clock\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "PHP-FIG",
+ "homepage": "https://www.php-fig.org/"
+ }
+ ],
+ "description": "Common interface for reading the clock.",
+ "homepage": "https://github.com/php-fig/clock",
+ "keywords": [
+ "clock",
+ "now",
+ "psr",
+ "psr-20",
+ "time"
+ ],
+ "support": {
+ "issues": "https://github.com/php-fig/clock/issues",
+ "source": "https://github.com/php-fig/clock/tree/1.0.0"
+ },
+ "time": "2022-11-25T14:36:26+00:00"
+ },
+ {
+ "name": "psr/container",
+ "version": "2.0.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/php-fig/container.git",
+ "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/php-fig/container/zipball/c71ecc56dfe541dbd90c5360474fbc405f8d5963",
+ "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.4.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.0.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Psr\\Container\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "PHP-FIG",
+ "homepage": "https://www.php-fig.org/"
+ }
+ ],
+ "description": "Common Container Interface (PHP FIG PSR-11)",
+ "homepage": "https://github.com/php-fig/container",
+ "keywords": [
+ "PSR-11",
+ "container",
+ "container-interface",
+ "container-interop",
+ "psr"
+ ],
+ "support": {
+ "issues": "https://github.com/php-fig/container/issues",
+ "source": "https://github.com/php-fig/container/tree/2.0.2"
+ },
+ "time": "2021-11-05T16:47:00+00:00"
+ },
+ {
+ "name": "psr/event-dispatcher",
+ "version": "1.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/php-fig/event-dispatcher.git",
+ "reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/php-fig/event-dispatcher/zipball/dbefd12671e8a14ec7f180cab83036ed26714bb0",
+ "reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.2.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.0.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Psr\\EventDispatcher\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "PHP-FIG",
+ "homepage": "http://www.php-fig.org/"
+ }
+ ],
+ "description": "Standard interfaces for event handling.",
+ "keywords": [
+ "events",
+ "psr",
+ "psr-14"
+ ],
+ "support": {
+ "issues": "https://github.com/php-fig/event-dispatcher/issues",
+ "source": "https://github.com/php-fig/event-dispatcher/tree/1.0.0"
+ },
+ "time": "2019-01-08T18:20:26+00:00"
+ },
+ {
+ "name": "psr/http-client",
+ "version": "1.0.3",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/php-fig/http-client.git",
+ "reference": "bb5906edc1c324c9a05aa0873d40117941e5fa90"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/php-fig/http-client/zipball/bb5906edc1c324c9a05aa0873d40117941e5fa90",
+ "reference": "bb5906edc1c324c9a05aa0873d40117941e5fa90",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^7.0 || ^8.0",
+ "psr/http-message": "^1.0 || ^2.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.0.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Psr\\Http\\Client\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "PHP-FIG",
+ "homepage": "https://www.php-fig.org/"
+ }
+ ],
+ "description": "Common interface for HTTP clients",
+ "homepage": "https://github.com/php-fig/http-client",
+ "keywords": [
+ "http",
+ "http-client",
+ "psr",
+ "psr-18"
+ ],
+ "support": {
+ "source": "https://github.com/php-fig/http-client"
+ },
+ "time": "2023-09-23T14:17:50+00:00"
+ },
+ {
+ "name": "psr/http-factory",
+ "version": "1.1.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/php-fig/http-factory.git",
+ "reference": "2b4765fddfe3b508ac62f829e852b1501d3f6e8a"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/php-fig/http-factory/zipball/2b4765fddfe3b508ac62f829e852b1501d3f6e8a",
+ "reference": "2b4765fddfe3b508ac62f829e852b1501d3f6e8a",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.1",
+ "psr/http-message": "^1.0 || ^2.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.0.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Psr\\Http\\Message\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "PHP-FIG",
+ "homepage": "https://www.php-fig.org/"
+ }
+ ],
+ "description": "PSR-17: Common interfaces for PSR-7 HTTP message factories",
+ "keywords": [
+ "factory",
+ "http",
+ "message",
+ "psr",
+ "psr-17",
+ "psr-7",
+ "request",
+ "response"
+ ],
+ "support": {
+ "source": "https://github.com/php-fig/http-factory"
+ },
+ "time": "2024-04-15T12:06:14+00:00"
+ },
+ {
+ "name": "psr/http-message",
+ "version": "2.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/php-fig/http-message.git",
+ "reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/php-fig/http-message/zipball/402d35bcb92c70c026d1a6a9883f06b2ead23d71",
+ "reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^7.2 || ^8.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.0.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Psr\\Http\\Message\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "PHP-FIG",
+ "homepage": "https://www.php-fig.org/"
+ }
+ ],
+ "description": "Common interface for HTTP messages",
+ "homepage": "https://github.com/php-fig/http-message",
+ "keywords": [
+ "http",
+ "http-message",
+ "psr",
+ "psr-7",
+ "request",
+ "response"
+ ],
+ "support": {
+ "source": "https://github.com/php-fig/http-message/tree/2.0"
+ },
+ "time": "2023-04-04T09:54:51+00:00"
+ },
+ {
+ "name": "psr/log",
+ "version": "3.0.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/php-fig/log.git",
+ "reference": "f16e1d5863e37f8d8c2a01719f5b34baa2b714d3"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/php-fig/log/zipball/f16e1d5863e37f8d8c2a01719f5b34baa2b714d3",
+ "reference": "f16e1d5863e37f8d8c2a01719f5b34baa2b714d3",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.0.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "3.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Psr\\Log\\": "src"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "PHP-FIG",
+ "homepage": "https://www.php-fig.org/"
+ }
+ ],
+ "description": "Common interface for logging libraries",
+ "homepage": "https://github.com/php-fig/log",
+ "keywords": [
+ "log",
+ "psr",
+ "psr-3"
+ ],
+ "support": {
+ "source": "https://github.com/php-fig/log/tree/3.0.2"
+ },
+ "time": "2024-09-11T13:17:53+00:00"
+ },
+ {
+ "name": "psr/simple-cache",
+ "version": "3.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/php-fig/simple-cache.git",
+ "reference": "764e0b3939f5ca87cb904f570ef9be2d78a07865"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/php-fig/simple-cache/zipball/764e0b3939f5ca87cb904f570ef9be2d78a07865",
+ "reference": "764e0b3939f5ca87cb904f570ef9be2d78a07865",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.0.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "3.0.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Psr\\SimpleCache\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "PHP-FIG",
+ "homepage": "https://www.php-fig.org/"
+ }
+ ],
+ "description": "Common interfaces for simple caching",
+ "keywords": [
+ "cache",
+ "caching",
+ "psr",
+ "psr-16",
+ "simple-cache"
+ ],
+ "support": {
+ "source": "https://github.com/php-fig/simple-cache/tree/3.0.0"
+ },
+ "time": "2021-10-29T13:26:27+00:00"
+ },
+ {
+ "name": "ralouphie/getallheaders",
+ "version": "3.0.3",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/ralouphie/getallheaders.git",
+ "reference": "120b605dfeb996808c31b6477290a714d356e822"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/ralouphie/getallheaders/zipball/120b605dfeb996808c31b6477290a714d356e822",
+ "reference": "120b605dfeb996808c31b6477290a714d356e822",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.6"
+ },
+ "require-dev": {
+ "php-coveralls/php-coveralls": "^2.1",
+ "phpunit/phpunit": "^5 || ^6.5"
+ },
+ "type": "library",
+ "autoload": {
+ "files": [
+ "src/getallheaders.php"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Ralph Khattar",
+ "email": "ralph.khattar@gmail.com"
+ }
+ ],
+ "description": "A polyfill for getallheaders.",
+ "support": {
+ "issues": "https://github.com/ralouphie/getallheaders/issues",
+ "source": "https://github.com/ralouphie/getallheaders/tree/develop"
+ },
+ "time": "2019-03-08T08:55:37+00:00"
+ },
+ {
+ "name": "ramsey/collection",
+ "version": "2.1.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/ramsey/collection.git",
+ "reference": "344572933ad0181accbf4ba763e85a0306a8c5e2"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/ramsey/collection/zipball/344572933ad0181accbf4ba763e85a0306a8c5e2",
+ "reference": "344572933ad0181accbf4ba763e85a0306a8c5e2",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^8.1"
+ },
+ "require-dev": {
+ "captainhook/plugin-composer": "^5.3",
+ "ergebnis/composer-normalize": "^2.45",
+ "fakerphp/faker": "^1.24",
+ "hamcrest/hamcrest-php": "^2.0",
+ "jangregor/phpstan-prophecy": "^2.1",
+ "mockery/mockery": "^1.6",
+ "php-parallel-lint/php-console-highlighter": "^1.0",
+ "php-parallel-lint/php-parallel-lint": "^1.4",
+ "phpspec/prophecy-phpunit": "^2.3",
+ "phpstan/extension-installer": "^1.4",
+ "phpstan/phpstan": "^2.1",
+ "phpstan/phpstan-mockery": "^2.0",
+ "phpstan/phpstan-phpunit": "^2.0",
+ "phpunit/phpunit": "^10.5",
+ "ramsey/coding-standard": "^2.3",
+ "ramsey/conventional-commits": "^1.6",
+ "roave/security-advisories": "dev-latest"
+ },
+ "type": "library",
+ "extra": {
+ "captainhook": {
+ "force-install": true
+ },
+ "ramsey/conventional-commits": {
+ "configFile": "conventional-commits.json"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Ramsey\\Collection\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Ben Ramsey",
+ "email": "ben@benramsey.com",
+ "homepage": "https://benramsey.com"
+ }
+ ],
+ "description": "A PHP library for representing and manipulating collections.",
+ "keywords": [
+ "array",
+ "collection",
+ "hash",
+ "map",
+ "queue",
+ "set"
+ ],
+ "support": {
+ "issues": "https://github.com/ramsey/collection/issues",
+ "source": "https://github.com/ramsey/collection/tree/2.1.1"
+ },
+ "time": "2025-03-22T05:38:12+00:00"
+ },
+ {
+ "name": "ramsey/uuid",
+ "version": "4.9.3",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/ramsey/uuid.git",
+ "reference": "1df15849d00943a67d677dc9cfd80795f038c9f8"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/ramsey/uuid/zipball/1df15849d00943a67d677dc9cfd80795f038c9f8",
+ "reference": "1df15849d00943a67d677dc9cfd80795f038c9f8",
+ "shasum": ""
+ },
+ "require": {
+ "brick/math": ">=0.8.16 <=0.18",
+ "php": "^8.0",
+ "ramsey/collection": "^1.2 || ^2.0"
+ },
+ "replace": {
+ "rhumsaa/uuid": "self.version"
+ },
+ "require-dev": {
+ "captainhook/captainhook": "^5.25",
+ "captainhook/plugin-composer": "^5.3",
+ "dealerdirect/phpcodesniffer-composer-installer": "^1.0",
+ "ergebnis/composer-normalize": "^2.47",
+ "mockery/mockery": "^1.6",
+ "paragonie/random-lib": "^2",
+ "php-mock/php-mock": "^2.6",
+ "php-mock/php-mock-mockery": "^1.5",
+ "php-parallel-lint/php-parallel-lint": "^1.4.0",
+ "phpbench/phpbench": "^1.2.14",
+ "phpstan/extension-installer": "^1.4",
+ "phpstan/phpstan": "^2.1",
+ "phpstan/phpstan-mockery": "^2.0",
+ "phpstan/phpstan-phpunit": "^2.0",
+ "phpunit/phpunit": "^9.6",
+ "slevomat/coding-standard": "^8.18",
+ "squizlabs/php_codesniffer": "^3.13"
+ },
+ "suggest": {
+ "ext-bcmath": "Enables faster math with arbitrary-precision integers using BCMath.",
+ "ext-gmp": "Enables faster math with arbitrary-precision integers using GMP.",
+ "ext-uuid": "Enables the use of PeclUuidTimeGenerator and PeclUuidRandomGenerator.",
+ "paragonie/random-lib": "Provides RandomLib for use with the RandomLibAdapter",
+ "ramsey/uuid-doctrine": "Allows the use of Ramsey\\Uuid\\Uuid as Doctrine field type."
+ },
+ "type": "library",
+ "extra": {
+ "captainhook": {
+ "force-install": true
+ }
+ },
+ "autoload": {
+ "files": [
+ "src/functions.php"
+ ],
+ "psr-4": {
+ "Ramsey\\Uuid\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "description": "A PHP library for generating and working with universally unique identifiers (UUIDs).",
+ "keywords": [
+ "guid",
+ "identifier",
+ "uuid"
+ ],
+ "support": {
+ "issues": "https://github.com/ramsey/uuid/issues",
+ "source": "https://github.com/ramsey/uuid/tree/4.9.3"
+ },
+ "time": "2026-06-18T03:57:49+00:00"
+ },
+ {
+ "name": "rector/rector",
+ "version": "2.6.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/rectorphp/rector.git",
+ "reference": "b8e68f058bca43e01a2e1caa51ef022d6551ed95"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/rectorphp/rector/zipball/b8e68f058bca43e01a2e1caa51ef022d6551ed95",
+ "reference": "b8e68f058bca43e01a2e1caa51ef022d6551ed95",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^7.4|^8.0",
+ "phpstan/phpstan": "^2.2.6"
+ },
+ "conflict": {
+ "rector/rector-doctrine": "*",
+ "rector/rector-downgrade-php": "*",
+ "rector/rector-phpunit": "*",
+ "rector/rector-symfony": "*"
+ },
+ "suggest": {
+ "ext-dom": "To manipulate phpunit.xml via the custom-rule command"
+ },
+ "bin": [
+ "bin/rector"
+ ],
+ "type": "library",
+ "autoload": {
+ "files": [
+ "bootstrap.php"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "description": "Instant Upgrade and Automated Refactoring of any PHP code",
+ "homepage": "https://getrector.com/",
+ "keywords": [
+ "automation",
+ "dev",
+ "migration",
+ "refactoring"
+ ],
+ "support": {
+ "issues": "https://github.com/rectorphp/rector/issues",
+ "source": "https://github.com/rectorphp/rector/tree/2.6.1"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/tomasvotruba",
+ "type": "github"
+ }
+ ],
+ "time": "2026-08-03T17:30:34+00:00"
+ },
+ {
+ "name": "sentry/sentry",
+ "version": "4.30.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/getsentry/sentry-php.git",
+ "reference": "95a26e7c946651cacd69d1ded95a8190f952a3ae"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/getsentry/sentry-php/zipball/95a26e7c946651cacd69d1ded95a8190f952a3ae",
+ "reference": "95a26e7c946651cacd69d1ded95a8190f952a3ae",
+ "shasum": ""
+ },
+ "require": {
+ "ext-curl": "*",
+ "ext-json": "*",
+ "ext-mbstring": "*",
+ "guzzlehttp/psr7": "^1.8.4|^2.1.1|^3.0.0",
+ "jean85/pretty-package-versions": "^1.5|^2.0.4",
+ "php": "^7.2|^8.0",
+ "psr/log": "^1.0|^2.0|^3.0",
+ "symfony/options-resolver": "^4.4.30|^5.0.11|^6.0|^7.0|^8.0"
+ },
+ "conflict": {
+ "raven/raven": "*"
+ },
+ "require-dev": {
+ "carthage-software/mago": "1.30.0",
+ "friendsofphp/php-cs-fixer": "^3.4",
+ "guzzlehttp/guzzle": "^7.0|^8.0",
+ "guzzlehttp/promises": "^2.0.3|^3.0.0",
+ "monolog/monolog": "^1.6|^2.0|^3.0",
+ "nyholm/psr7": "^1.8",
+ "open-telemetry/api": "^1.1",
+ "open-telemetry/context": "^1.1",
+ "open-telemetry/exporter-otlp": "^1.1",
+ "open-telemetry/sdk": "^1.1",
+ "open-telemetry/sem-conv": "^1.27",
+ "phpstan/phpstan": "^1.3",
+ "phpunit/phpunit": "^8.5.52|^9.6.34",
+ "spiral/roadrunner-http": "^3.6",
+ "spiral/roadrunner-worker": "^3.6"
+ },
+ "suggest": {
+ "ext-excimer": "Enable Sentry profiling with the Excimer PHP extension.",
+ "monolog/monolog": "Allow sending log messages to Sentry by using the included Monolog handler."
+ },
+ "type": "library",
+ "autoload": {
+ "files": [
+ "src/functions.php"
+ ],
+ "psr-4": {
+ "Sentry\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Sentry",
+ "email": "accounts@sentry.io"
+ }
+ ],
+ "description": "PHP SDK for Sentry (http://sentry.io)",
+ "homepage": "http://sentry.io",
+ "keywords": [
+ "crash-reporting",
+ "crash-reports",
+ "error-handler",
+ "error-monitoring",
+ "log",
+ "logging",
+ "profiling",
+ "sentry",
+ "tracing"
+ ],
+ "support": {
+ "issues": "https://github.com/getsentry/sentry-php/issues",
+ "source": "https://github.com/getsentry/sentry-php/tree/4.30.0"
+ },
+ "funding": [
+ {
+ "url": "https://sentry.io/",
+ "type": "custom"
+ },
+ {
+ "url": "https://sentry.io/pricing/",
+ "type": "custom"
+ }
+ ],
+ "time": "2026-08-05T14:54:26+00:00"
+ },
+ {
+ "name": "sentry/sentry-laravel",
+ "version": "4.27.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/getsentry/sentry-laravel.git",
+ "reference": "caa0ff39805a2eb8c70c4535a1443d7421c5a5b8"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/getsentry/sentry-laravel/zipball/caa0ff39805a2eb8c70c4535a1443d7421c5a5b8",
+ "reference": "caa0ff39805a2eb8c70c4535a1443d7421c5a5b8",
+ "shasum": ""
+ },
+ "require": {
+ "illuminate/support": "^6.0 | ^7.0 | ^8.0 | ^9.0 | ^10.0 | ^11.0 | ^12.0 | ^13.0",
+ "nyholm/psr7": "^1.0",
+ "php": "^7.2 | ^8.0",
+ "sentry/sentry": "^4.28.0",
+ "symfony/psr-http-message-bridge": "^1.0 | ^2.0 | ^6.0 | ^7.0 | ^8.0"
+ },
+ "require-dev": {
+ "friendsofphp/php-cs-fixer": "^3.11",
+ "guzzlehttp/guzzle": "^7.2",
+ "laravel/ai": "^0.1.5",
+ "laravel/folio": "^1.1",
+ "laravel/framework": "^6.0 | ^7.0 | ^8.0 | ^9.0 | ^10.0 | ^11.0 | ^12.0 | ^13.0",
+ "laravel/octane": "^2.15",
+ "laravel/pennant": "^1.0",
+ "livewire/livewire": "^2.0 | ^3.0 | ^4.0",
+ "mockery/mockery": "^1.3",
+ "orchestra/testbench": "^4.7 | ^5.1 | ^6.0 | ^7.0 | ^8.0 | ^9.0 | ^10.0 | ^11.0",
+ "phpstan/phpstan": "^1.10",
+ "phpunit/phpunit": "^8.5 | ^9.6 | ^10.4 | ^11.5"
+ },
+ "type": "library",
+ "extra": {
+ "laravel": {
+ "aliases": {
+ "Sentry": "Sentry\\Laravel\\Facade"
+ },
+ "providers": [
+ "Sentry\\Laravel\\ServiceProvider",
+ "Sentry\\Laravel\\Tracing\\ServiceProvider"
+ ]
+ }
+ },
+ "autoload": {
+ "psr-0": {
+ "Sentry\\Laravel\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Sentry",
+ "email": "accounts@sentry.io"
+ }
+ ],
+ "description": "Laravel SDK for Sentry (https://sentry.io)",
+ "homepage": "https://sentry.io",
+ "keywords": [
+ "crash-reporting",
+ "crash-reports",
+ "error-handler",
+ "error-monitoring",
+ "laravel",
+ "log",
+ "logging",
+ "profiling",
+ "sentry",
+ "tracing"
+ ],
+ "support": {
+ "issues": "https://github.com/getsentry/sentry-laravel/issues",
+ "source": "https://github.com/getsentry/sentry-laravel/tree/4.27.0"
+ },
+ "funding": [
+ {
+ "url": "https://sentry.io/",
+ "type": "custom"
+ },
+ {
+ "url": "https://sentry.io/pricing/",
+ "type": "custom"
+ }
+ ],
+ "time": "2026-07-15T14:47:03+00:00"
+ },
+ {
+ "name": "symfony/clock",
+ "version": "v8.1.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/clock.git",
+ "reference": "701ef4de9705d6c32292ebee5e8044094a09fbf6"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/clock/zipball/701ef4de9705d6c32292ebee5e8044094a09fbf6",
+ "reference": "701ef4de9705d6c32292ebee5e8044094a09fbf6",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.4.1",
+ "psr/clock": "^1.0"
+ },
+ "provide": {
+ "psr/clock-implementation": "1.0"
+ },
+ "type": "library",
+ "autoload": {
+ "files": [
+ "Resources/now.php"
+ ],
+ "psr-4": {
+ "Symfony\\Component\\Clock\\": ""
+ },
+ "exclude-from-classmap": [
+ "/Tests/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Nicolas Grekas",
+ "email": "p@tchwork.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Decouples applications from the system clock",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "clock",
+ "psr20",
+ "time"
+ ],
+ "support": {
+ "source": "https://github.com/symfony/clock/tree/v8.1.0"
+ },
+ "funding": [
+ {
+ "url": "https://symfony.com/sponsor",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/fabpot",
+ "type": "github"
+ },
+ {
+ "url": "https://github.com/nicolas-grekas",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2026-05-29T05:06:50+00:00"
+ },
+ {
+ "name": "symfony/console",
+ "version": "v8.1.4",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/console.git",
+ "reference": "68efa2ebfd9a362951eb5a8b09fd177c66ddec24"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/console/zipball/68efa2ebfd9a362951eb5a8b09fd177c66ddec24",
+ "reference": "68efa2ebfd9a362951eb5a8b09fd177c66ddec24",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.4.1",
+ "symfony/deprecation-contracts": "^2.5|^3",
+ "symfony/polyfill-mbstring": "^1.0",
+ "symfony/polyfill-php85": "^1.32",
+ "symfony/service-contracts": "^2.5|^3",
+ "symfony/string": "^7.4.6|^8.0.6"
+ },
+ "conflict": {
+ "symfony/dependency-injection": "<8.1",
+ "symfony/event-dispatcher": "<8.1"
+ },
+ "provide": {
+ "psr/log-implementation": "1.0|2.0|3.0"
+ },
+ "require-dev": {
+ "psr/log": "^1|^2|^3",
+ "symfony/config": "^7.4|^8.0",
+ "symfony/dependency-injection": "^8.1",
+ "symfony/event-dispatcher": "^8.1",
+ "symfony/filesystem": "^7.4|^8.0",
+ "symfony/http-foundation": "^7.4|^8.0",
+ "symfony/http-kernel": "^7.4|^8.0",
+ "symfony/lock": "^7.4|^8.0",
+ "symfony/messenger": "^7.4|^8.0",
+ "symfony/mime": "^7.4|^8.0",
+ "symfony/process": "^7.4|^8.0",
+ "symfony/stopwatch": "^7.4|^8.0",
+ "symfony/uid": "^7.4|^8.0",
+ "symfony/validator": "^7.4|^8.0",
+ "symfony/var-dumper": "^7.4|^8.0"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Component\\Console\\": ""
+ },
+ "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": "Eases the creation of beautiful and testable command line interfaces",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "cli",
+ "command-line",
+ "console",
+ "terminal"
+ ],
+ "support": {
+ "source": "https://github.com/symfony/console/tree/v8.1.4"
+ },
+ "funding": [
+ {
+ "url": "https://symfony.com/sponsor",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/fabpot",
+ "type": "github"
+ },
+ {
+ "url": "https://github.com/nicolas-grekas",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2026-07-31T12:43:13+00:00"
+ },
+ {
+ "name": "symfony/css-selector",
+ "version": "v8.1.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/css-selector.git",
+ "reference": "dc0e2be45c9b5588c82414f02ac574b4b986abcd"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/css-selector/zipball/dc0e2be45c9b5588c82414f02ac574b4b986abcd",
+ "reference": "dc0e2be45c9b5588c82414f02ac574b4b986abcd",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.4.1"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Component\\CssSelector\\": ""
+ },
+ "exclude-from-classmap": [
+ "/Tests/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com"
+ },
+ {
+ "name": "Jean-François Simon",
+ "email": "jeanfrancois.simon@sensiolabs.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Converts CSS selectors to XPath expressions",
+ "homepage": "https://symfony.com",
+ "support": {
+ "source": "https://github.com/symfony/css-selector/tree/v8.1.0"
+ },
+ "funding": [
+ {
+ "url": "https://symfony.com/sponsor",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/fabpot",
+ "type": "github"
+ },
+ {
+ "url": "https://github.com/nicolas-grekas",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2026-05-29T05:06:50+00:00"
+ },
+ {
+ "name": "symfony/deprecation-contracts",
+ "version": "v3.7.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/deprecation-contracts.git",
+ "reference": "f3202fa1b5097b0af062dc978b32ecf63404e31d"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/f3202fa1b5097b0af062dc978b32ecf63404e31d",
+ "reference": "f3202fa1b5097b0af062dc978b32ecf63404e31d",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.1"
+ },
+ "type": "library",
+ "extra": {
+ "thanks": {
+ "url": "https://github.com/symfony/contracts",
+ "name": "symfony/contracts"
+ },
+ "branch-alias": {
+ "dev-main": "3.7-dev"
+ }
+ },
+ "autoload": {
+ "files": [
+ "function.php"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Nicolas Grekas",
+ "email": "p@tchwork.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "A generic function and convention to trigger deprecation notices",
+ "homepage": "https://symfony.com",
+ "support": {
+ "source": "https://github.com/symfony/deprecation-contracts/tree/v3.7.1"
+ },
+ "funding": [
+ {
+ "url": "https://symfony.com/sponsor",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/fabpot",
+ "type": "github"
+ },
+ {
+ "url": "https://github.com/nicolas-grekas",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2026-06-05T06:23:12+00:00"
+ },
+ {
+ "name": "symfony/error-handler",
+ "version": "v8.1.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/error-handler.git",
+ "reference": "dc98404be5e8c949815e23fee1928f5de4f3f5d3"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/error-handler/zipball/dc98404be5e8c949815e23fee1928f5de4f3f5d3",
+ "reference": "dc98404be5e8c949815e23fee1928f5de4f3f5d3",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.4.1",
+ "psr/log": "^1|^2|^3",
+ "symfony/polyfill-php85": "^1.32",
+ "symfony/var-dumper": "^7.4|^8.0"
+ },
+ "conflict": {
+ "symfony/deprecation-contracts": "<2.5"
+ },
+ "require-dev": {
+ "symfony/console": "^7.4|^8.0",
+ "symfony/deprecation-contracts": "^2.5|^3",
+ "symfony/http-kernel": "^7.4|^8.0",
+ "symfony/serializer": "^7.4|^8.0",
+ "symfony/webpack-encore-bundle": "^1.0|^2.0"
+ },
+ "bin": [
+ "Resources/bin/patch-type-declarations"
+ ],
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Component\\ErrorHandler\\": ""
+ },
+ "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 tools to manage errors and ease debugging PHP code",
+ "homepage": "https://symfony.com",
+ "support": {
+ "source": "https://github.com/symfony/error-handler/tree/v8.1.2"
+ },
+ "funding": [
+ {
+ "url": "https://symfony.com/sponsor",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/fabpot",
+ "type": "github"
+ },
+ {
+ "url": "https://github.com/nicolas-grekas",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2026-07-22T15:42:13+00:00"
+ },
+ {
+ "name": "symfony/event-dispatcher",
+ "version": "v8.1.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/event-dispatcher.git",
+ "reference": "c14c05a9e6da7f5e375e6efc28952c7e7dbddffb"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/c14c05a9e6da7f5e375e6efc28952c7e7dbddffb",
+ "reference": "c14c05a9e6da7f5e375e6efc28952c7e7dbddffb",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.4.1",
+ "symfony/deprecation-contracts": "^2.5|^3",
+ "symfony/event-dispatcher-contracts": "^2.5|^3"
+ },
+ "conflict": {
+ "symfony/security-http": "<7.4",
+ "symfony/service-contracts": "<2.5"
+ },
+ "provide": {
+ "psr/event-dispatcher-implementation": "1.0",
+ "symfony/event-dispatcher-implementation": "2.0|3.0"
+ },
+ "require-dev": {
+ "psr/log": "^1|^2|^3",
+ "symfony/config": "^7.4|^8.0",
+ "symfony/dependency-injection": "^7.4|^8.0",
+ "symfony/error-handler": "^7.4|^8.0",
+ "symfony/expression-language": "^7.4|^8.0",
+ "symfony/framework-bundle": "^7.4|^8.0",
+ "symfony/http-foundation": "^7.4|^8.0",
+ "symfony/service-contracts": "^2.5|^3",
+ "symfony/stopwatch": "^7.4|^8.0"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Component\\EventDispatcher\\": ""
+ },
+ "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 tools that allow your application components to communicate with each other by dispatching events and listening to them",
+ "homepage": "https://symfony.com",
+ "support": {
+ "source": "https://github.com/symfony/event-dispatcher/tree/v8.1.2"
+ },
+ "funding": [
+ {
+ "url": "https://symfony.com/sponsor",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/fabpot",
+ "type": "github"
+ },
+ {
+ "url": "https://github.com/nicolas-grekas",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2026-07-22T15:42:13+00:00"
+ },
+ {
+ "name": "symfony/event-dispatcher-contracts",
+ "version": "v3.7.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/event-dispatcher-contracts.git",
+ "reference": "c7de7a00ffb67842132da02ea92988a39ccd9f4e"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/c7de7a00ffb67842132da02ea92988a39ccd9f4e",
+ "reference": "c7de7a00ffb67842132da02ea92988a39ccd9f4e",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.1",
+ "psr/event-dispatcher": "^1"
+ },
+ "type": "library",
+ "extra": {
+ "thanks": {
+ "url": "https://github.com/symfony/contracts",
+ "name": "symfony/contracts"
+ },
+ "branch-alias": {
+ "dev-main": "3.7-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Contracts\\EventDispatcher\\": ""
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Nicolas Grekas",
+ "email": "p@tchwork.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Generic abstractions related to dispatching event",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "abstractions",
+ "contracts",
+ "decoupling",
+ "interfaces",
+ "interoperability",
+ "standards"
+ ],
+ "support": {
+ "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v3.7.1"
+ },
+ "funding": [
+ {
+ "url": "https://symfony.com/sponsor",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/fabpot",
+ "type": "github"
+ },
+ {
+ "url": "https://github.com/nicolas-grekas",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2026-06-05T06:23:12+00:00"
+ },
+ {
+ "name": "symfony/finder",
+ "version": "v8.1.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/finder.git",
+ "reference": "e2989e762c70f9490fa3a00a0ac0fae5aa97a531"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/finder/zipball/e2989e762c70f9490fa3a00a0ac0fae5aa97a531",
+ "reference": "e2989e762c70f9490fa3a00a0ac0fae5aa97a531",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.4.1"
+ },
+ "require-dev": {
+ "symfony/filesystem": "^7.4|^8.0"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Component\\Finder\\": ""
+ },
+ "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": "Finds files and directories via an intuitive fluent interface",
+ "homepage": "https://symfony.com",
+ "support": {
+ "source": "https://github.com/symfony/finder/tree/v8.1.1"
+ },
+ "funding": [
+ {
+ "url": "https://symfony.com/sponsor",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/fabpot",
+ "type": "github"
+ },
+ {
+ "url": "https://github.com/nicolas-grekas",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2026-06-27T09:05:56+00:00"
+ },
+ {
+ "name": "symfony/http-foundation",
+ "version": "v8.1.4",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/http-foundation.git",
+ "reference": "57e712b75f2d0bc8844edbdb18a81dab6f9d55c2"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/http-foundation/zipball/57e712b75f2d0bc8844edbdb18a81dab6f9d55c2",
+ "reference": "57e712b75f2d0bc8844edbdb18a81dab6f9d55c2",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.4.1",
+ "symfony/deprecation-contracts": "^2.5|^3",
+ "symfony/polyfill-mbstring": "^1.1"
+ },
+ "conflict": {
+ "doctrine/dbal": "<4.3"
+ },
+ "require-dev": {
+ "doctrine/dbal": "^4.3",
+ "predis/predis": "^1.1|^2.0",
+ "symfony/cache": "^7.4|^8.0",
+ "symfony/clock": "^7.4|^8.0",
+ "symfony/dependency-injection": "^7.4|^8.0",
+ "symfony/expression-language": "^7.4|^8.0",
+ "symfony/http-kernel": "^7.4|^8.0",
+ "symfony/mime": "^7.4|^8.0",
+ "symfony/rate-limiter": "^7.4|^8.0"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Component\\HttpFoundation\\": ""
+ },
+ "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": "Defines an object-oriented layer for the HTTP specification",
+ "homepage": "https://symfony.com",
+ "support": {
+ "source": "https://github.com/symfony/http-foundation/tree/v8.1.4"
+ },
+ "funding": [
+ {
+ "url": "https://symfony.com/sponsor",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/fabpot",
+ "type": "github"
+ },
+ {
+ "url": "https://github.com/nicolas-grekas",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2026-08-07T15:02:39+00:00"
+ },
+ {
+ "name": "symfony/http-kernel",
+ "version": "v8.1.4",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/http-kernel.git",
+ "reference": "69d81d8a5dac32a5d94e4eb063b7d97dc42c792a"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/http-kernel/zipball/69d81d8a5dac32a5d94e4eb063b7d97dc42c792a",
+ "reference": "69d81d8a5dac32a5d94e4eb063b7d97dc42c792a",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.4.1",
+ "psr/log": "^1|^2|^3",
+ "symfony/deprecation-contracts": "^2.5|^3",
+ "symfony/error-handler": "^7.4|^8.0",
+ "symfony/event-dispatcher": "^7.4|^8.0",
+ "symfony/http-foundation": "^7.4|^8.0",
+ "symfony/polyfill-ctype": "^1.8"
+ },
+ "conflict": {
+ "symfony/dependency-injection": "<8.1",
+ "symfony/flex": "<2.10",
+ "symfony/http-client-contracts": "<2.5",
+ "symfony/serializer": "<7.4.15|>=8.0,<8.0.15|>=8.1,<8.1.2",
+ "symfony/translation-contracts": "<2.5",
+ "symfony/var-dumper": "<8.1",
+ "symfony/web-profiler-bundle": "<8.1",
+ "twig/twig": "<3.21"
+ },
+ "provide": {
+ "psr/log-implementation": "1.0|2.0|3.0"
+ },
+ "require-dev": {
+ "psr/cache": "^1.0|^2.0|^3.0",
+ "symfony/browser-kit": "^7.4|^8.0",
+ "symfony/clock": "^7.4|^8.0",
+ "symfony/config": "^7.4|^8.0",
+ "symfony/console": "^7.4|^8.0",
+ "symfony/css-selector": "^7.4|^8.0",
+ "symfony/dependency-injection": "^8.1",
+ "symfony/dom-crawler": "^7.4|^8.0",
+ "symfony/expression-language": "^7.4|^8.0",
+ "symfony/finder": "^7.4|^8.0",
+ "symfony/http-client-contracts": "^2.5|^3",
+ "symfony/process": "^7.4|^8.0",
+ "symfony/property-access": "^7.4|^8.0",
+ "symfony/rate-limiter": "^7.4|^8.0",
+ "symfony/routing": "^7.4|^8.0",
+ "symfony/serializer": "^7.4|^8.0",
+ "symfony/stopwatch": "^7.4|^8.0",
+ "symfony/translation": "^7.4|^8.0",
+ "symfony/translation-contracts": "^2.5|^3",
+ "symfony/uid": "^7.4|^8.0",
+ "symfony/validator": "^7.4|^8.0",
+ "symfony/var-dumper": "^8.1",
+ "symfony/var-exporter": "^7.4|^8.0",
+ "twig/twig": "^3.21|^4.0"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Component\\HttpKernel\\": ""
+ },
+ "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 structured process for converting a Request into a Response",
+ "homepage": "https://symfony.com",
+ "support": {
+ "source": "https://github.com/symfony/http-kernel/tree/v8.1.4"
+ },
+ "funding": [
+ {
+ "url": "https://symfony.com/sponsor",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/fabpot",
+ "type": "github"
+ },
+ {
+ "url": "https://github.com/nicolas-grekas",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2026-08-07T18:04:54+00:00"
+ },
+ {
+ "name": "symfony/mailer",
+ "version": "v8.1.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/mailer.git",
+ "reference": "221c7f326ace1ac2baee8331d829d5b7f04f4d53"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/mailer/zipball/221c7f326ace1ac2baee8331d829d5b7f04f4d53",
+ "reference": "221c7f326ace1ac2baee8331d829d5b7f04f4d53",
+ "shasum": ""
+ },
+ "require": {
+ "egulias/email-validator": "^2.1.10|^3|^4",
+ "php": ">=8.4.1",
+ "psr/event-dispatcher": "^1",
+ "psr/log": "^1|^2|^3",
+ "symfony/event-dispatcher": "^7.4|^8.0",
+ "symfony/mime": "^7.4|^8.0",
+ "symfony/service-contracts": "^2.5|^3"
+ },
+ "conflict": {
+ "symfony/http-client-contracts": "<2.5"
+ },
+ "require-dev": {
+ "symfony/console": "^7.4|^8.0",
+ "symfony/http-client": "^7.4|^8.0",
+ "symfony/messenger": "^7.4|^8.0",
+ "symfony/twig-bridge": "^7.4|^8.0"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Component\\Mailer\\": ""
+ },
+ "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": "Helps sending emails",
+ "homepage": "https://symfony.com",
+ "support": {
+ "source": "https://github.com/symfony/mailer/tree/v8.1.2"
+ },
+ "funding": [
+ {
+ "url": "https://symfony.com/sponsor",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/fabpot",
+ "type": "github"
+ },
+ {
+ "url": "https://github.com/nicolas-grekas",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2026-07-28T07:35:25+00:00"
+ },
+ {
+ "name": "symfony/mime",
+ "version": "v8.1.4",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/mime.git",
+ "reference": "8f8ac859d369fe3d18e3837998b1c992bbee92c9"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/mime/zipball/8f8ac859d369fe3d18e3837998b1c992bbee92c9",
+ "reference": "8f8ac859d369fe3d18e3837998b1c992bbee92c9",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.4.1",
+ "symfony/polyfill-intl-idn": "^1.10",
+ "symfony/polyfill-mbstring": "^1.0"
+ },
+ "conflict": {
+ "egulias/email-validator": "~3.0.0",
+ "phpdocumentor/reflection-docblock": "<5.2|>=7",
+ "phpdocumentor/type-resolver": "<1.5.1"
+ },
+ "require-dev": {
+ "egulias/email-validator": "^2.1.10|^3.1|^4",
+ "league/html-to-markdown": "^5.0",
+ "phpdocumentor/reflection-docblock": "^5.2|^6.0",
+ "symfony/dependency-injection": "^7.4|^8.0",
+ "symfony/process": "^7.4|^8.0",
+ "symfony/property-access": "^7.4|^8.0",
+ "symfony/property-info": "^7.4|^8.0",
+ "symfony/serializer": "^7.4|^8.0"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Component\\Mime\\": ""
+ },
+ "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": "Allows manipulating MIME messages",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "mime",
+ "mime-type"
+ ],
+ "support": {
+ "source": "https://github.com/symfony/mime/tree/v8.1.4"
+ },
+ "funding": [
+ {
+ "url": "https://symfony.com/sponsor",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/fabpot",
+ "type": "github"
+ },
+ {
+ "url": "https://github.com/nicolas-grekas",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2026-08-07T15:02:39+00:00"
+ },
+ {
+ "name": "symfony/options-resolver",
+ "version": "v8.1.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/options-resolver.git",
+ "reference": "88f9c561f678a02d54b897014049fa839e33ff82"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/options-resolver/zipball/88f9c561f678a02d54b897014049fa839e33ff82",
+ "reference": "88f9c561f678a02d54b897014049fa839e33ff82",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.4.1",
+ "symfony/deprecation-contracts": "^2.5|^3"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Component\\OptionsResolver\\": ""
+ },
+ "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 an improved replacement for the array_replace PHP function",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "config",
+ "configuration",
+ "options"
+ ],
+ "support": {
+ "source": "https://github.com/symfony/options-resolver/tree/v8.1.0"
+ },
+ "funding": [
+ {
+ "url": "https://symfony.com/sponsor",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/fabpot",
+ "type": "github"
+ },
+ {
+ "url": "https://github.com/nicolas-grekas",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2026-05-29T05:06:50+00:00"
+ },
+ {
+ "name": "symfony/polyfill-ctype",
+ "version": "v1.37.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/polyfill-ctype.git",
+ "reference": "141046a8f9477948ff284fa65be2095baafb94f2"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/141046a8f9477948ff284fa65be2095baafb94f2",
+ "reference": "141046a8f9477948ff284fa65be2095baafb94f2",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.2"
+ },
+ "provide": {
+ "ext-ctype": "*"
+ },
+ "suggest": {
+ "ext-ctype": "For best performance"
+ },
+ "type": "library",
+ "extra": {
+ "thanks": {
+ "url": "https://github.com/symfony/polyfill",
+ "name": "symfony/polyfill"
+ }
+ },
+ "autoload": {
+ "files": [
+ "bootstrap.php"
+ ],
+ "psr-4": {
+ "Symfony\\Polyfill\\Ctype\\": ""
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Gert de Pagter",
+ "email": "BackEndTea@gmail.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Symfony polyfill for ctype functions",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "compatibility",
+ "ctype",
+ "polyfill",
+ "portable"
+ ],
+ "support": {
+ "source": "https://github.com/symfony/polyfill-ctype/tree/v1.37.0"
+ },
+ "funding": [
+ {
+ "url": "https://symfony.com/sponsor",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/fabpot",
+ "type": "github"
+ },
+ {
+ "url": "https://github.com/nicolas-grekas",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2026-04-10T16:19:22+00:00"
+ },
+ {
+ "name": "symfony/polyfill-intl-grapheme",
+ "version": "v1.41.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/polyfill-intl-grapheme.git",
+ "reference": "bb899c1db0aa8127dc3afe8cda4a67eb24915f8d"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/bb899c1db0aa8127dc3afe8cda4a67eb24915f8d",
+ "reference": "bb899c1db0aa8127dc3afe8cda4a67eb24915f8d",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.2"
+ },
+ "suggest": {
+ "ext-intl": "For best performance"
+ },
+ "type": "library",
+ "extra": {
+ "thanks": {
+ "url": "https://github.com/symfony/polyfill",
+ "name": "symfony/polyfill"
+ }
+ },
+ "autoload": {
+ "files": [
+ "bootstrap.php"
+ ],
+ "psr-4": {
+ "Symfony\\Polyfill\\Intl\\Grapheme\\": ""
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Nicolas Grekas",
+ "email": "p@tchwork.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Symfony polyfill for intl's grapheme_* functions",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "compatibility",
+ "grapheme",
+ "intl",
+ "polyfill",
+ "portable",
+ "shim"
+ ],
+ "support": {
+ "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.41.0"
+ },
+ "funding": [
+ {
+ "url": "https://symfony.com/sponsor",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/fabpot",
+ "type": "github"
+ },
+ {
+ "url": "https://github.com/nicolas-grekas",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2026-07-28T08:25:59+00:00"
+ },
+ {
+ "name": "symfony/polyfill-intl-idn",
+ "version": "v1.38.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/polyfill-intl-idn.git",
+ "reference": "dc21118016c039a66235cf93d96b435ffb282412"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/dc21118016c039a66235cf93d96b435ffb282412",
+ "reference": "dc21118016c039a66235cf93d96b435ffb282412",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.2",
+ "symfony/polyfill-intl-normalizer": "^1.10"
+ },
+ "suggest": {
+ "ext-intl": "For best performance"
+ },
+ "type": "library",
+ "extra": {
+ "thanks": {
+ "url": "https://github.com/symfony/polyfill",
+ "name": "symfony/polyfill"
+ }
+ },
+ "autoload": {
+ "files": [
+ "bootstrap.php"
+ ],
+ "psr-4": {
+ "Symfony\\Polyfill\\Intl\\Idn\\": ""
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Laurent Bassin",
+ "email": "laurent@bassin.info"
+ },
+ {
+ "name": "Trevor Rowbotham",
+ "email": "trevor.rowbotham@pm.me"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Symfony polyfill for intl's idn_to_ascii and idn_to_utf8 functions",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "compatibility",
+ "idn",
+ "intl",
+ "polyfill",
+ "portable",
+ "shim"
+ ],
+ "support": {
+ "source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.38.1"
+ },
+ "funding": [
+ {
+ "url": "https://symfony.com/sponsor",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/fabpot",
+ "type": "github"
+ },
+ {
+ "url": "https://github.com/nicolas-grekas",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2026-05-25T15:22:23+00:00"
+ },
+ {
+ "name": "symfony/polyfill-intl-normalizer",
+ "version": "v1.38.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/polyfill-intl-normalizer.git",
+ "reference": "2d446c214bdbe5b71bde5011b060a05fece3ae6b"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/2d446c214bdbe5b71bde5011b060a05fece3ae6b",
+ "reference": "2d446c214bdbe5b71bde5011b060a05fece3ae6b",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.2"
+ },
+ "suggest": {
+ "ext-intl": "For best performance"
+ },
+ "type": "library",
+ "extra": {
+ "thanks": {
+ "url": "https://github.com/symfony/polyfill",
+ "name": "symfony/polyfill"
+ }
+ },
+ "autoload": {
+ "files": [
+ "bootstrap.php"
+ ],
+ "psr-4": {
+ "Symfony\\Polyfill\\Intl\\Normalizer\\": ""
+ },
+ "classmap": [
+ "Resources/stubs"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Nicolas Grekas",
+ "email": "p@tchwork.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Symfony polyfill for intl's Normalizer class and related functions",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "compatibility",
+ "intl",
+ "normalizer",
+ "polyfill",
+ "portable",
+ "shim"
+ ],
+ "support": {
+ "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.38.0"
+ },
+ "funding": [
+ {
+ "url": "https://symfony.com/sponsor",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/fabpot",
+ "type": "github"
+ },
+ {
+ "url": "https://github.com/nicolas-grekas",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2026-05-25T13:48:31+00:00"
+ },
+ {
+ "name": "symfony/polyfill-mbstring",
+ "version": "v1.38.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/polyfill-mbstring.git",
+ "reference": "d3d318bad5e7a1bfbd026009c8bfb8d8f99ae6b6"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/d3d318bad5e7a1bfbd026009c8bfb8d8f99ae6b6",
+ "reference": "d3d318bad5e7a1bfbd026009c8bfb8d8f99ae6b6",
+ "shasum": ""
+ },
+ "require": {
+ "ext-iconv": "*",
+ "php": ">=7.2"
+ },
+ "provide": {
+ "ext-mbstring": "*"
+ },
+ "suggest": {
+ "ext-mbstring": "For best performance"
+ },
+ "type": "library",
+ "extra": {
+ "thanks": {
+ "url": "https://github.com/symfony/polyfill",
+ "name": "symfony/polyfill"
+ }
+ },
+ "autoload": {
+ "files": [
+ "bootstrap.php"
+ ],
+ "psr-4": {
+ "Symfony\\Polyfill\\Mbstring\\": ""
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Nicolas Grekas",
+ "email": "p@tchwork.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Symfony polyfill for the Mbstring extension",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "compatibility",
+ "mbstring",
+ "polyfill",
+ "portable",
+ "shim"
+ ],
+ "support": {
+ "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.38.2"
+ },
+ "funding": [
+ {
+ "url": "https://symfony.com/sponsor",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/fabpot",
+ "type": "github"
+ },
+ {
+ "url": "https://github.com/nicolas-grekas",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2026-05-27T06:59:30+00:00"
+ },
+ {
+ "name": "symfony/polyfill-php80",
+ "version": "v1.37.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/polyfill-php80.git",
+ "reference": "dfb55726c3a76ea3b6459fcfda1ec2d80a682411"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/dfb55726c3a76ea3b6459fcfda1ec2d80a682411",
+ "reference": "dfb55726c3a76ea3b6459fcfda1ec2d80a682411",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.2"
+ },
+ "type": "library",
+ "extra": {
+ "thanks": {
+ "url": "https://github.com/symfony/polyfill",
+ "name": "symfony/polyfill"
+ }
+ },
+ "autoload": {
+ "files": [
+ "bootstrap.php"
+ ],
+ "psr-4": {
+ "Symfony\\Polyfill\\Php80\\": ""
+ },
+ "classmap": [
+ "Resources/stubs"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Ion Bazan",
+ "email": "ion.bazan@gmail.com"
+ },
+ {
+ "name": "Nicolas Grekas",
+ "email": "p@tchwork.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "compatibility",
+ "polyfill",
+ "portable",
+ "shim"
+ ],
+ "support": {
+ "source": "https://github.com/symfony/polyfill-php80/tree/v1.37.0"
+ },
+ "funding": [
+ {
+ "url": "https://symfony.com/sponsor",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/fabpot",
+ "type": "github"
+ },
+ {
+ "url": "https://github.com/nicolas-grekas",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2026-04-10T16:19:22+00:00"
+ },
+ {
+ "name": "symfony/polyfill-php84",
+ "version": "v1.38.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/polyfill-php84.git",
+ "reference": "f4e1dfaee5b74aba5964fe1fd4dfc7ba5e3085fa"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/polyfill-php84/zipball/f4e1dfaee5b74aba5964fe1fd4dfc7ba5e3085fa",
+ "reference": "f4e1dfaee5b74aba5964fe1fd4dfc7ba5e3085fa",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.2"
+ },
+ "type": "library",
+ "extra": {
+ "thanks": {
+ "url": "https://github.com/symfony/polyfill",
+ "name": "symfony/polyfill"
+ }
+ },
+ "autoload": {
+ "files": [
+ "bootstrap.php"
+ ],
+ "psr-4": {
+ "Symfony\\Polyfill\\Php84\\": ""
+ },
+ "classmap": [
+ "Resources/stubs"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Nicolas Grekas",
+ "email": "p@tchwork.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Symfony polyfill backporting some PHP 8.4+ features to lower PHP versions",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "compatibility",
+ "polyfill",
+ "portable",
+ "shim"
+ ],
+ "support": {
+ "source": "https://github.com/symfony/polyfill-php84/tree/v1.38.1"
+ },
+ "funding": [
+ {
+ "url": "https://symfony.com/sponsor",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/fabpot",
+ "type": "github"
+ },
+ {
+ "url": "https://github.com/nicolas-grekas",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2026-05-26T12:51:13+00:00"
+ },
+ {
+ "name": "symfony/polyfill-php85",
+ "version": "v1.41.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/polyfill-php85.git",
+ "reference": "255fab485aaa1006ed411040c42aecd7b5302d7a"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/polyfill-php85/zipball/255fab485aaa1006ed411040c42aecd7b5302d7a",
+ "reference": "255fab485aaa1006ed411040c42aecd7b5302d7a",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.2"
+ },
+ "type": "library",
+ "extra": {
+ "thanks": {
+ "url": "https://github.com/symfony/polyfill",
+ "name": "symfony/polyfill"
+ }
+ },
+ "autoload": {
+ "files": [
+ "bootstrap.php"
+ ],
+ "psr-4": {
+ "Symfony\\Polyfill\\Php85\\": ""
+ },
+ "classmap": [
+ "Resources/stubs"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Nicolas Grekas",
+ "email": "p@tchwork.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Symfony polyfill backporting some PHP 8.5+ features to lower PHP versions",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "compatibility",
+ "polyfill",
+ "portable",
+ "shim"
+ ],
+ "support": {
+ "source": "https://github.com/symfony/polyfill-php85/tree/v1.41.0"
+ },
+ "funding": [
+ {
+ "url": "https://symfony.com/sponsor",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/fabpot",
+ "type": "github"
+ },
+ {
+ "url": "https://github.com/nicolas-grekas",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2026-07-01T12:47:55+00:00"
+ },
+ {
+ "name": "symfony/polyfill-php86",
+ "version": "v1.41.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/polyfill-php86.git",
+ "reference": "6bc356ed3d8dbfeea8f0de235e34d670704e880e"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/polyfill-php86/zipball/6bc356ed3d8dbfeea8f0de235e34d670704e880e",
+ "reference": "6bc356ed3d8dbfeea8f0de235e34d670704e880e",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.2"
+ },
+ "type": "library",
+ "extra": {
+ "thanks": {
+ "url": "https://github.com/symfony/polyfill",
+ "name": "symfony/polyfill"
+ }
+ },
+ "autoload": {
+ "files": [
+ "bootstrap.php"
+ ],
+ "psr-4": {
+ "Symfony\\Polyfill\\Php86\\": ""
+ },
+ "classmap": [
+ "Resources/stubs"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Nicolas Grekas",
+ "email": "p@tchwork.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Symfony polyfill backporting some PHP 8.6+ features to lower PHP versions",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "compatibility",
+ "polyfill",
+ "portable",
+ "shim"
+ ],
+ "support": {
+ "source": "https://github.com/symfony/polyfill-php86/tree/v1.41.0"
+ },
+ "funding": [
+ {
+ "url": "https://symfony.com/sponsor",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/fabpot",
+ "type": "github"
+ },
+ {
+ "url": "https://github.com/nicolas-grekas",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2026-07-02T13:42:24+00:00"
+ },
+ {
+ "name": "symfony/polyfill-uuid",
+ "version": "v1.37.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/polyfill-uuid.git",
+ "reference": "26dfec253c4cf3e51b541b52ddf7e42cb0908e94"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/polyfill-uuid/zipball/26dfec253c4cf3e51b541b52ddf7e42cb0908e94",
+ "reference": "26dfec253c4cf3e51b541b52ddf7e42cb0908e94",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.2"
+ },
+ "provide": {
+ "ext-uuid": "*"
+ },
+ "suggest": {
+ "ext-uuid": "For best performance"
+ },
+ "type": "library",
+ "extra": {
+ "thanks": {
+ "url": "https://github.com/symfony/polyfill",
+ "name": "symfony/polyfill"
+ }
+ },
+ "autoload": {
+ "files": [
+ "bootstrap.php"
+ ],
+ "psr-4": {
+ "Symfony\\Polyfill\\Uuid\\": ""
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Grégoire Pineau",
+ "email": "lyrixx@lyrixx.info"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Symfony polyfill for uuid functions",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "compatibility",
+ "polyfill",
+ "portable",
+ "uuid"
+ ],
+ "support": {
+ "source": "https://github.com/symfony/polyfill-uuid/tree/v1.37.0"
+ },
+ "funding": [
+ {
+ "url": "https://symfony.com/sponsor",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/fabpot",
+ "type": "github"
+ },
+ {
+ "url": "https://github.com/nicolas-grekas",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2026-04-10T16:19:22+00:00"
+ },
+ {
+ "name": "symfony/process",
+ "version": "v8.1.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/process.git",
+ "reference": "c4a9e58f235a6bf7f97ffbfedae2687353ac79e5"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/process/zipball/c4a9e58f235a6bf7f97ffbfedae2687353ac79e5",
+ "reference": "c4a9e58f235a6bf7f97ffbfedae2687353ac79e5",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.4.1"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Component\\Process\\": ""
+ },
+ "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": "Executes commands in sub-processes",
+ "homepage": "https://symfony.com",
+ "support": {
+ "source": "https://github.com/symfony/process/tree/v8.1.0"
+ },
+ "funding": [
+ {
+ "url": "https://symfony.com/sponsor",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/fabpot",
+ "type": "github"
+ },
+ {
+ "url": "https://github.com/nicolas-grekas",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2026-05-29T05:06:50+00:00"
+ },
+ {
+ "name": "symfony/psr-http-message-bridge",
+ "version": "v8.1.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/psr-http-message-bridge.git",
+ "reference": "67fd34de15ded1763aa1e330fe345f080a94022c"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/psr-http-message-bridge/zipball/67fd34de15ded1763aa1e330fe345f080a94022c",
+ "reference": "67fd34de15ded1763aa1e330fe345f080a94022c",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.4.1",
+ "psr/http-message": "^1.0|^2.0",
+ "symfony/http-foundation": "^7.4|^8.0"
+ },
+ "conflict": {
+ "php-http/discovery": "<1.15"
+ },
+ "require-dev": {
+ "nyholm/psr7": "^1.1",
+ "php-http/discovery": "^1.15",
+ "psr/log": "^1.1.4|^2|^3",
+ "symfony/browser-kit": "^7.4|^8.0",
+ "symfony/config": "^7.4|^8.0",
+ "symfony/event-dispatcher": "^7.4|^8.0",
+ "symfony/framework-bundle": "^7.4|^8.0",
+ "symfony/http-kernel": "^7.4|^8.0",
+ "symfony/runtime": "^7.4|^8.0"
+ },
+ "type": "symfony-bridge",
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Bridge\\PsrHttpMessage\\": ""
+ },
+ "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": "PSR HTTP message bridge",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "http",
+ "http-message",
+ "psr-17",
+ "psr-7"
+ ],
+ "support": {
+ "source": "https://github.com/symfony/psr-http-message-bridge/tree/v8.1.0"
+ },
+ "funding": [
+ {
+ "url": "https://symfony.com/sponsor",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/fabpot",
+ "type": "github"
+ },
+ {
+ "url": "https://github.com/nicolas-grekas",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2026-05-29T05:06:50+00:00"
+ },
+ {
+ "name": "symfony/routing",
+ "version": "v8.1.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/routing.git",
+ "reference": "1058d4e13bb81dd9a6f7565686df7e13b880cdbd"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/routing/zipball/1058d4e13bb81dd9a6f7565686df7e13b880cdbd",
+ "reference": "1058d4e13bb81dd9a6f7565686df7e13b880cdbd",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.4.1",
+ "symfony/deprecation-contracts": "^2.5|^3"
+ },
+ "require-dev": {
+ "psr/log": "^1|^2|^3",
+ "symfony/config": "^7.4|^8.0",
+ "symfony/dependency-injection": "^7.4|^8.0",
+ "symfony/expression-language": "^7.4|^8.0",
+ "symfony/http-foundation": "^7.4|^8.0",
+ "symfony/yaml": "^7.4|^8.0"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Component\\Routing\\": ""
+ },
+ "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": "Maps an HTTP request to a set of configuration variables",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "router",
+ "routing",
+ "uri",
+ "url"
+ ],
+ "support": {
+ "source": "https://github.com/symfony/routing/tree/v8.1.2"
+ },
+ "funding": [
+ {
+ "url": "https://symfony.com/sponsor",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/fabpot",
+ "type": "github"
+ },
+ {
+ "url": "https://github.com/nicolas-grekas",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2026-07-22T15:42:13+00:00"
+ },
+ {
+ "name": "symfony/service-contracts",
+ "version": "v3.7.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/service-contracts.git",
+ "reference": "c0a284bab1ed8aa0417e3d69250ab437739563a0"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/service-contracts/zipball/c0a284bab1ed8aa0417e3d69250ab437739563a0",
+ "reference": "c0a284bab1ed8aa0417e3d69250ab437739563a0",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.1",
+ "psr/container": "^1.1|^2.0",
+ "symfony/deprecation-contracts": "^2.5|^3"
+ },
+ "conflict": {
+ "ext-psr": "<1.1|>=2"
+ },
+ "type": "library",
+ "extra": {
+ "thanks": {
+ "url": "https://github.com/symfony/contracts",
+ "name": "symfony/contracts"
+ },
+ "branch-alias": {
+ "dev-main": "3.7-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Contracts\\Service\\": ""
+ },
+ "exclude-from-classmap": [
+ "/Test/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Nicolas Grekas",
+ "email": "p@tchwork.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Generic abstractions related to writing services",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "abstractions",
+ "contracts",
+ "decoupling",
+ "interfaces",
+ "interoperability",
+ "standards"
+ ],
+ "support": {
+ "source": "https://github.com/symfony/service-contracts/tree/v3.7.1"
+ },
+ "funding": [
+ {
+ "url": "https://symfony.com/sponsor",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/fabpot",
+ "type": "github"
+ },
+ {
+ "url": "https://github.com/nicolas-grekas",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2026-06-16T09:55:08+00:00"
+ },
+ {
+ "name": "symfony/string",
+ "version": "v8.1.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/string.git",
+ "reference": "286a76b7255e5cc4bf0101a0bc5388ecf1c38ccc"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/string/zipball/286a76b7255e5cc4bf0101a0bc5388ecf1c38ccc",
+ "reference": "286a76b7255e5cc4bf0101a0bc5388ecf1c38ccc",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.4.1",
+ "symfony/polyfill-ctype": "^1.8",
+ "symfony/polyfill-intl-grapheme": "^1.33",
+ "symfony/polyfill-intl-normalizer": "^1.0",
+ "symfony/polyfill-mbstring": "^1.0"
+ },
+ "conflict": {
+ "symfony/translation-contracts": "<2.5"
+ },
+ "require-dev": {
+ "symfony/emoji": "^7.4|^8.0",
+ "symfony/http-client": "^7.4|^8.0",
+ "symfony/intl": "^7.4|^8.0",
+ "symfony/translation-contracts": "^2.5|^3.0",
+ "symfony/var-exporter": "^7.4|^8.0"
+ },
+ "type": "library",
+ "autoload": {
+ "files": [
+ "Resources/functions.php"
+ ],
+ "psr-4": {
+ "Symfony\\Component\\String\\": ""
+ },
+ "exclude-from-classmap": [
+ "/Tests/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Nicolas Grekas",
+ "email": "p@tchwork.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Provides an object-oriented API to strings and deals with bytes, UTF-8 code points and grapheme clusters in a unified way",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "grapheme",
+ "i18n",
+ "string",
+ "unicode",
+ "utf-8",
+ "utf8"
+ ],
+ "support": {
+ "source": "https://github.com/symfony/string/tree/v8.1.2"
+ },
+ "funding": [
+ {
+ "url": "https://symfony.com/sponsor",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/fabpot",
+ "type": "github"
+ },
+ {
+ "url": "https://github.com/nicolas-grekas",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2026-07-28T07:35:25+00:00"
+ },
+ {
+ "name": "symfony/translation",
+ "version": "v8.1.4",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/translation.git",
+ "reference": "c0955eb4aa417a110e65c8162237b8a5c7d910bf"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/translation/zipball/c0955eb4aa417a110e65c8162237b8a5c7d910bf",
+ "reference": "c0955eb4aa417a110e65c8162237b8a5c7d910bf",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.4.1",
+ "symfony/polyfill-mbstring": "^1.0",
+ "symfony/translation-contracts": "^3.6.1"
+ },
+ "conflict": {
+ "nikic/php-parser": "<5.0",
+ "symfony/http-client-contracts": "<2.5",
+ "symfony/service-contracts": "<2.5"
+ },
+ "provide": {
+ "symfony/translation-implementation": "2.3|3.0"
+ },
+ "require-dev": {
+ "nikic/php-parser": "^5.0",
+ "psr/log": "^1|^2|^3",
+ "symfony/config": "^7.4|^8.0",
+ "symfony/console": "^7.4|^8.0",
+ "symfony/dependency-injection": "^7.4|^8.0",
+ "symfony/finder": "^7.4|^8.0",
+ "symfony/http-client-contracts": "^2.5|^3.0",
+ "symfony/http-kernel": "^7.4|^8.0",
+ "symfony/intl": "^7.4|^8.0",
+ "symfony/polyfill-intl-icu": "^1.21",
+ "symfony/routing": "^7.4|^8.0",
+ "symfony/service-contracts": "^2.5|^3",
+ "symfony/yaml": "^7.4|^8.0"
+ },
+ "type": "library",
+ "autoload": {
+ "files": [
+ "Resources/functions.php"
+ ],
+ "psr-4": {
+ "Symfony\\Component\\Translation\\": ""
+ },
+ "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 tools to internationalize your application",
+ "homepage": "https://symfony.com",
+ "support": {
+ "source": "https://github.com/symfony/translation/tree/v8.1.4"
+ },
+ "funding": [
+ {
+ "url": "https://symfony.com/sponsor",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/fabpot",
+ "type": "github"
+ },
+ {
+ "url": "https://github.com/nicolas-grekas",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2026-07-30T12:40:56+00:00"
+ },
+ {
+ "name": "symfony/translation-contracts",
+ "version": "v3.7.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/translation-contracts.git",
+ "reference": "ccb206b98faccc511ebae8e5fad50f2dc0b30621"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/ccb206b98faccc511ebae8e5fad50f2dc0b30621",
+ "reference": "ccb206b98faccc511ebae8e5fad50f2dc0b30621",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.1"
+ },
+ "type": "library",
+ "extra": {
+ "thanks": {
+ "url": "https://github.com/symfony/contracts",
+ "name": "symfony/contracts"
+ },
+ "branch-alias": {
+ "dev-main": "3.7-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Contracts\\Translation\\": ""
+ },
+ "exclude-from-classmap": [
+ "/Test/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Nicolas Grekas",
+ "email": "p@tchwork.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Generic abstractions related to translation",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "abstractions",
+ "contracts",
+ "decoupling",
+ "interfaces",
+ "interoperability",
+ "standards"
+ ],
+ "support": {
+ "source": "https://github.com/symfony/translation-contracts/tree/v3.7.1"
+ },
+ "funding": [
+ {
+ "url": "https://symfony.com/sponsor",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/fabpot",
+ "type": "github"
+ },
+ {
+ "url": "https://github.com/nicolas-grekas",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2026-06-05T06:23:12+00:00"
+ },
+ {
+ "name": "symfony/uid",
+ "version": "v8.1.4",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/uid.git",
+ "reference": "50e98f8bc4c3fcdaf925545a65150fb42cf0caf2"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/uid/zipball/50e98f8bc4c3fcdaf925545a65150fb42cf0caf2",
+ "reference": "50e98f8bc4c3fcdaf925545a65150fb42cf0caf2",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.4.1",
+ "symfony/polyfill-uuid": "^1.15"
+ },
+ "require-dev": {
+ "symfony/console": "^7.4|^8.0"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Component\\Uid\\": ""
+ },
+ "exclude-from-classmap": [
+ "/Tests/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Grégoire Pineau",
+ "email": "lyrixx@lyrixx.info"
+ },
+ {
+ "name": "Nicolas Grekas",
+ "email": "p@tchwork.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Provides an object-oriented API to generate and represent UIDs",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "UID",
+ "ulid",
+ "uuid"
+ ],
+ "support": {
+ "source": "https://github.com/symfony/uid/tree/v8.1.4"
+ },
+ "funding": [
+ {
+ "url": "https://symfony.com/sponsor",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/fabpot",
+ "type": "github"
+ },
+ {
+ "url": "https://github.com/nicolas-grekas",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2026-08-02T11:29:46+00:00"
+ },
+ {
+ "name": "symfony/var-dumper",
+ "version": "v8.1.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/var-dumper.git",
+ "reference": "865103cf742a039f34645b971fc3ace308d6c167"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/var-dumper/zipball/865103cf742a039f34645b971fc3ace308d6c167",
+ "reference": "865103cf742a039f34645b971fc3ace308d6c167",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.4.1",
+ "symfony/polyfill-mbstring": "^1.0"
+ },
+ "conflict": {
+ "symfony/console": "<7.4",
+ "symfony/error-handler": "<7.4"
+ },
+ "require-dev": {
+ "symfony/console": "^7.4|^8.0",
+ "symfony/http-kernel": "^7.4|^8.0",
+ "symfony/process": "^7.4|^8.0",
+ "symfony/uid": "^7.4|^8.0",
+ "twig/twig": "^3.12|^4.0"
+ },
+ "bin": [
+ "Resources/bin/var-dump-server"
+ ],
+ "type": "library",
+ "autoload": {
+ "files": [
+ "Resources/functions/dump.php"
+ ],
+ "psr-4": {
+ "Symfony\\Component\\VarDumper\\": ""
+ },
+ "exclude-from-classmap": [
+ "/Tests/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Nicolas Grekas",
+ "email": "p@tchwork.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Provides mechanisms for walking through any arbitrary PHP variable",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "debug",
+ "dump"
+ ],
+ "support": {
+ "source": "https://github.com/symfony/var-dumper/tree/v8.1.2"
+ },
+ "funding": [
+ {
+ "url": "https://symfony.com/sponsor",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/fabpot",
+ "type": "github"
+ },
+ {
+ "url": "https://github.com/nicolas-grekas",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2026-07-22T15:42:13+00:00"
+ },
+ {
+ "name": "tijsverkoyen/css-to-inline-styles",
+ "version": "v2.4.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/tijsverkoyen/CssToInlineStyles.git",
+ "reference": "f0292ccf0ec75843d65027214426b6b163b48b41"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/tijsverkoyen/CssToInlineStyles/zipball/f0292ccf0ec75843d65027214426b6b163b48b41",
+ "reference": "f0292ccf0ec75843d65027214426b6b163b48b41",
+ "shasum": ""
+ },
+ "require": {
+ "ext-dom": "*",
+ "ext-libxml": "*",
+ "php": "^7.4 || ^8.0",
+ "symfony/css-selector": "^5.4 || ^6.0 || ^7.0 || ^8.0"
+ },
+ "require-dev": {
+ "phpstan/phpstan": "^2.0",
+ "phpstan/phpstan-phpunit": "^2.0",
+ "phpunit/phpunit": "^8.5.21 || ^9.5.10"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "TijsVerkoyen\\CssToInlineStyles\\": "src"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Tijs Verkoyen",
+ "email": "css_to_inline_styles@verkoyen.eu",
+ "role": "Developer"
+ }
+ ],
+ "description": "CssToInlineStyles is a class that enables you to convert HTML-pages/files into HTML-pages/files with inline styles. This is very useful when you're sending emails.",
+ "homepage": "https://github.com/tijsverkoyen/CssToInlineStyles",
+ "support": {
+ "issues": "https://github.com/tijsverkoyen/CssToInlineStyles/issues",
+ "source": "https://github.com/tijsverkoyen/CssToInlineStyles/tree/v2.4.0"
+ },
+ "time": "2025-12-02T11:56:42+00:00"
+ },
+ {
+ "name": "vlucas/phpdotenv",
+ "version": "v5.6.4",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/vlucas/phpdotenv.git",
+ "reference": "416df702837983f8d5ff48c9c3fee4f5f57b980b"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/vlucas/phpdotenv/zipball/416df702837983f8d5ff48c9c3fee4f5f57b980b",
+ "reference": "416df702837983f8d5ff48c9c3fee4f5f57b980b",
+ "shasum": ""
+ },
+ "require": {
+ "ext-pcre": "*",
+ "graham-campbell/result-type": "^1.1.4",
+ "php": "^7.2.5 || ^8.0",
+ "phpoption/phpoption": "^1.9.5",
+ "symfony/polyfill-ctype": "^1.26",
+ "symfony/polyfill-mbstring": "^1.26",
+ "symfony/polyfill-php80": "^1.26"
+ },
+ "require-dev": {
+ "bamarni/composer-bin-plugin": "^1.8.2",
+ "ext-filter": "*",
+ "phpunit/phpunit": "^8.5.34 || ^9.6.13 || ^10.4.2"
+ },
+ "suggest": {
+ "ext-filter": "Required to use the boolean validator."
+ },
+ "type": "library",
+ "extra": {
+ "bamarni-bin": {
+ "bin-links": true,
+ "forward-command": false
+ },
+ "branch-alias": {
+ "dev-master": "5.6-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Dotenv\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Graham Campbell",
+ "email": "hello@gjcampbell.co.uk",
+ "homepage": "https://github.com/GrahamCampbell"
+ },
+ {
+ "name": "Vance Lucas",
+ "email": "vance@vancelucas.com",
+ "homepage": "https://github.com/vlucas"
+ }
+ ],
+ "description": "Loads environment variables from `.env` to `getenv()`, `$_ENV` and `$_SERVER` automagically.",
+ "keywords": [
+ "dotenv",
+ "env",
+ "environment"
+ ],
+ "support": {
+ "issues": "https://github.com/vlucas/phpdotenv/issues",
+ "source": "https://github.com/vlucas/phpdotenv/tree/v5.6.4"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/GrahamCampbell",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/vlucas/phpdotenv",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2026-07-06T19:11:50+00:00"
+ },
+ {
+ "name": "voku/portable-ascii",
+ "version": "2.1.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/voku/portable-ascii.git",
+ "reference": "8e1051fe39379367aecf014f41744ce7539a856f"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/voku/portable-ascii/zipball/8e1051fe39379367aecf014f41744ce7539a856f",
+ "reference": "8e1051fe39379367aecf014f41744ce7539a856f",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.1.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "~8.5 || ~9.6 || ~10.5 || ~11.5"
+ },
+ "suggest": {
+ "ext-intl": "Use Intl for transliterator_transliterate() support"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "voku\\": "src/voku/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Lars Moelleken",
+ "homepage": "https://www.moelleken.org/"
+ }
+ ],
+ "description": "Portable ASCII library - performance optimized (ascii) string functions for php.",
+ "homepage": "https://github.com/voku/portable-ascii",
+ "keywords": [
+ "ascii",
+ "clean",
+ "php"
+ ],
+ "support": {
+ "issues": "https://github.com/voku/portable-ascii/issues",
+ "source": "https://github.com/voku/portable-ascii/tree/2.1.1"
+ },
+ "funding": [
+ {
+ "url": "https://www.paypal.me/moelleken",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/voku",
+ "type": "github"
+ },
+ {
+ "url": "https://opencollective.com/portable-ascii",
+ "type": "open_collective"
+ },
+ {
+ "url": "https://www.patreon.com/voku",
+ "type": "patreon"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/voku/portable-ascii",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2026-04-26T05:33:54+00:00"
+ },
+ {
+ "name": "webmozart/assert",
+ "version": "2.4.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/webmozarts/assert.git",
+ "reference": "2ccb7c2e821038c03a3e6e1700c570c158c55f70"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/webmozarts/assert/zipball/2ccb7c2e821038c03a3e6e1700c570c158c55f70",
+ "reference": "2ccb7c2e821038c03a3e6e1700c570c158c55f70",
+ "shasum": ""
+ },
+ "require": {
+ "ext-ctype": "*",
+ "ext-date": "*",
+ "ext-filter": "*",
+ "php": "^8.2"
+ },
+ "suggest": {
+ "ext-intl": "",
+ "ext-simplexml": "",
+ "ext-spl": ""
+ },
+ "type": "library",
+ "extra": {
+ "psalm": {
+ "pluginClass": "Webmozart\\Assert\\PsalmPlugin"
+ },
+ "branch-alias": {
+ "dev-master": "2.0-dev",
+ "dev-feature/2-0": "2.0-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Webmozart\\Assert\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Bernhard Schussek",
+ "email": "bschussek@gmail.com"
+ },
+ {
+ "name": "Woody Gilk",
+ "email": "woody.gilk@gmail.com"
+ }
+ ],
+ "description": "Assertions to validate method input/output with nice error messages.",
+ "keywords": [
+ "assert",
+ "check",
+ "validate"
+ ],
+ "support": {
+ "issues": "https://github.com/webmozarts/assert/issues",
+ "source": "https://github.com/webmozarts/assert/tree/2.4.1"
+ },
+ "time": "2026-06-15T15:31:57+00:00"
+ }
+ ],
+ "packages-dev": [
+ {
+ "name": "ace-of-aces/intellipest",
+ "version": "v1.0.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/ace-of-aces/intellipest.git",
+ "reference": "51dd78f729f26fd814e31d24e5b6c412a144ed84"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/ace-of-aces/intellipest/zipball/51dd78f729f26fd814e31d24e5b6c412a144ed84",
+ "reference": "51dd78f729f26fd814e31d24e5b6c412a144ed84",
+ "shasum": ""
+ },
+ "require": {
+ "nikic/php-parser": "^5.7",
+ "php": "^8.3",
+ "react/event-loop": "^1.6",
+ "symfony/console": "^7.4.0 || ^8.0.0"
+ },
+ "require-dev": {
+ "carthage-software/mago": "^1.27.1",
+ "pestphp/pest": "^4.3"
+ },
+ "bin": [
+ "bin/intellipest"
+ ],
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "AceOfAces\\IntelliPest\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Julian Schramm",
+ "email": "hi@julian.center"
+ }
+ ],
+ "description": "Generate IDE helpers to assist development with PestPHP",
+ "support": {
+ "issues": "https://github.com/ace-of-aces/intellipest/issues",
+ "source": "https://github.com/ace-of-aces/intellipest/tree/v1.0.1"
+ },
+ "time": "2026-05-13T21:53:01+00:00"
+ },
+ {
+ "name": "barryvdh/laravel-ide-helper",
+ "version": "v3.7.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/barryvdh/laravel-ide-helper.git",
+ "reference": "ad7e37676f1ff985d55ef1b6b96a0c0a40f2609a"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/barryvdh/laravel-ide-helper/zipball/ad7e37676f1ff985d55ef1b6b96a0c0a40f2609a",
+ "reference": "ad7e37676f1ff985d55ef1b6b96a0c0a40f2609a",
+ "shasum": ""
+ },
+ "require": {
+ "barryvdh/reflection-docblock": "^2.4",
+ "composer/class-map-generator": "^1.0",
+ "ext-json": "*",
+ "illuminate/console": "^11.15 || ^12 || ^13.0",
+ "illuminate/database": "^11.15 || ^12 || ^13.0",
+ "illuminate/filesystem": "^11.15 || ^12 || ^13.0",
+ "illuminate/support": "^11.15 || ^12 || ^13.0",
+ "php": "^8.2"
+ },
+ "require-dev": {
+ "ext-pdo_sqlite": "*",
+ "friendsofphp/php-cs-fixer": "^3",
+ "illuminate/config": "^11.15 || ^12 || ^13.0",
+ "illuminate/view": "^11.15 || ^12 || ^13.0",
+ "larastan/larastan": "^3.1",
+ "mockery/mockery": "^1.4",
+ "orchestra/testbench": "^9.2 || ^10 || ^11.0",
+ "phpstan/phpstan-phpunit": "^2.0",
+ "phpunit/phpunit": "^10.5 || ^11.5.3 || ^12.5.12",
+ "spatie/phpunit-snapshot-assertions": "^4 || ^5",
+ "vlucas/phpdotenv": "^5"
+ },
+ "suggest": {
+ "illuminate/events": "Required for automatic helper generation (^6|^7|^8|^9|^10|^11)."
+ },
+ "type": "library",
+ "extra": {
+ "laravel": {
+ "providers": [
+ "Barryvdh\\LaravelIdeHelper\\IdeHelperServiceProvider"
+ ]
+ },
+ "branch-alias": {
+ "dev-master": "3.6-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Barryvdh\\LaravelIdeHelper\\": "src"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Barry vd. Heuvel",
+ "email": "barryvdh@gmail.com"
+ }
+ ],
+ "description": "Laravel IDE Helper, generates correct PHPDocs for all Facade classes, to improve auto-completion.",
+ "keywords": [
+ "autocomplete",
+ "codeintel",
+ "dev",
+ "helper",
+ "ide",
+ "laravel",
+ "netbeans",
+ "phpdoc",
+ "phpstorm",
+ "sublime"
+ ],
+ "support": {
+ "issues": "https://github.com/barryvdh/laravel-ide-helper/issues",
+ "source": "https://github.com/barryvdh/laravel-ide-helper/tree/v3.7.0"
+ },
+ "funding": [
+ {
+ "url": "https://fruitcake.nl",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/barryvdh",
+ "type": "github"
+ }
+ ],
+ "time": "2026-03-17T14:12:51+00:00"
+ },
+ {
+ "name": "barryvdh/reflection-docblock",
+ "version": "v2.4.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/barryvdh/ReflectionDocBlock.git",
+ "reference": "4f5ba70c30c81f2ce03a16a9965832cfcc31ed3b"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/barryvdh/ReflectionDocBlock/zipball/4f5ba70c30c81f2ce03a16a9965832cfcc31ed3b",
+ "reference": "4f5ba70c30c81f2ce03a16a9965832cfcc31ed3b",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.1"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^8.5.14|^9"
+ },
+ "suggest": {
+ "dflydev/markdown": "~1.0",
+ "erusev/parsedown": "~1.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.3.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-0": {
+ "Barryvdh": [
+ "src/"
+ ]
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Mike van Riel",
+ "email": "mike.vanriel@naenius.com"
+ }
+ ],
+ "support": {
+ "source": "https://github.com/barryvdh/ReflectionDocBlock/tree/v2.4.1"
+ },
+ "time": "2026-03-05T20:09:01+00:00"
+ },
+ {
+ "name": "brianium/paratest",
+ "version": "v7.20.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/paratestphp/paratest.git",
+ "reference": "81c80677c9ec0ed4ef16b246167f11dec81a6e3d"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/paratestphp/paratest/zipball/81c80677c9ec0ed4ef16b246167f11dec81a6e3d",
+ "reference": "81c80677c9ec0ed4ef16b246167f11dec81a6e3d",
+ "shasum": ""
+ },
+ "require": {
+ "ext-dom": "*",
+ "ext-pcre": "*",
+ "ext-reflection": "*",
+ "ext-simplexml": "*",
+ "fidry/cpu-core-counter": "^1.3.0",
+ "jean85/pretty-package-versions": "^2.1.1",
+ "php": "~8.3.0 || ~8.4.0 || ~8.5.0",
+ "phpunit/php-code-coverage": "^12.5.3 || ^13.0.1",
+ "phpunit/php-file-iterator": "^6.0.1 || ^7",
+ "phpunit/php-timer": "^8 || ^9",
+ "phpunit/phpunit": "^12.5.14 || ^13.0.5",
+ "sebastian/environment": "^8.0.3 || ^9",
+ "symfony/console": "^7.4.7 || ^8.0.7",
+ "symfony/process": "^7.4.5 || ^8.0.5"
+ },
+ "require-dev": {
+ "doctrine/coding-standard": "^14.0.0",
+ "ext-pcntl": "*",
+ "ext-pcov": "*",
+ "ext-posix": "*",
+ "phpstan/phpstan": "^2.1.44",
+ "phpstan/phpstan-deprecation-rules": "^2.0.4",
+ "phpstan/phpstan-phpunit": "^2.0.16",
+ "phpstan/phpstan-strict-rules": "^2.0.10",
+ "symfony/filesystem": "^7.4.6 || ^8.0.6"
+ },
+ "bin": [
+ "bin/paratest",
+ "bin/paratest_for_phpstorm"
+ ],
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "ParaTest\\": [
+ "src/"
+ ]
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Brian Scaturro",
+ "email": "scaturrob@gmail.com",
+ "role": "Developer"
+ },
+ {
+ "name": "Filippo Tessarotto",
+ "email": "zoeslam@gmail.com",
+ "role": "Developer"
+ }
+ ],
+ "description": "Parallel testing for PHP",
+ "homepage": "https://github.com/paratestphp/paratest",
+ "keywords": [
+ "concurrent",
+ "parallel",
+ "phpunit",
+ "testing"
+ ],
+ "support": {
+ "issues": "https://github.com/paratestphp/paratest/issues",
+ "source": "https://github.com/paratestphp/paratest/tree/v7.20.0"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sponsors/Slamdunk",
+ "type": "github"
+ },
+ {
+ "url": "https://paypal.me/filippotessarotto",
+ "type": "paypal"
+ }
+ ],
+ "time": "2026-03-29T15:46:14+00:00"
+ },
+ {
+ "name": "cebe/php-openapi",
+ "version": "1.8.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/cebe/php-openapi.git",
+ "reference": "893ab104be1f5dfe5a39766703f583584e43c6e1"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/cebe/php-openapi/zipball/893ab104be1f5dfe5a39766703f583584e43c6e1",
+ "reference": "893ab104be1f5dfe5a39766703f583584e43c6e1",
+ "shasum": ""
+ },
+ "require": {
+ "ext-json": "*",
+ "justinrainbow/json-schema": "^5.2 || ^6.0",
+ "php": ">=7.1.0",
+ "symfony/yaml": "^3.4 || ^4 || ^5 || ^6 || ^7.0"
+ },
+ "conflict": {
+ "symfony/yaml": "3.4.0 - 3.4.4 || 4.0.0 - 4.4.17 || 5.0.0 - 5.1.9 || 5.2.0"
+ },
+ "require-dev": {
+ "apis-guru/openapi-directory": "1.0.0",
+ "cebe/indent": "*",
+ "mermade/openapi3-examples": "1.0.0",
+ "nexmo/api-specification": "1.0.0",
+ "oai/openapi-specification": "3.0.3",
+ "phpstan/phpstan": "^0.12.0 || ^1.9",
+ "phpunit/phpunit": "^6.5 || ^7.5 || ^8.5 || ^9.4"
+ },
+ "bin": [
+ "bin/php-openapi"
+ ],
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.6.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "cebe\\openapi\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Carsten Brandt",
+ "email": "mail@cebe.cc",
+ "homepage": "https://cebe.cc/",
+ "role": "Creator"
+ }
+ ],
+ "description": "Read and write OpenAPI yaml/json files and make the content accessable in PHP objects.",
+ "homepage": "https://github.com/cebe/php-openapi#readme",
+ "keywords": [
+ "openapi"
+ ],
+ "support": {
+ "issues": "https://github.com/cebe/php-openapi/issues",
+ "source": "https://github.com/cebe/php-openapi"
+ },
+ "time": "2025-05-07T08:44:12+00:00"
+ },
+ {
+ "name": "composer/class-map-generator",
+ "version": "1.7.3",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/composer/class-map-generator.git",
+ "reference": "86d8208fc3c649a3a999daf1a63c25201be2990f"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/composer/class-map-generator/zipball/86d8208fc3c649a3a999daf1a63c25201be2990f",
+ "reference": "86d8208fc3c649a3a999daf1a63c25201be2990f",
+ "shasum": ""
+ },
+ "require": {
+ "composer/pcre": "^2.1 || ^3.1",
+ "php": "^7.2 || ^8.0",
+ "symfony/finder": "^4.4 || ^5.3 || ^6 || ^7 || ^8"
+ },
+ "require-dev": {
+ "phpstan/phpstan": "^1.12 || ^2",
+ "phpstan/phpstan-deprecation-rules": "^1 || ^2",
+ "phpstan/phpstan-phpunit": "^1 || ^2",
+ "phpstan/phpstan-strict-rules": "^1.1 || ^2",
+ "phpunit/phpunit": "^8",
+ "symfony/filesystem": "^5.4 || ^6 || ^7 || ^8"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "1.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Composer\\ClassMapGenerator\\": "src"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Jordi Boggiano",
+ "email": "j.boggiano@seld.be",
+ "homepage": "https://seld.be"
+ }
+ ],
+ "description": "Utilities to scan PHP code and generate class maps.",
+ "keywords": [
+ "classmap"
+ ],
+ "support": {
+ "issues": "https://github.com/composer/class-map-generator/issues",
+ "source": "https://github.com/composer/class-map-generator/tree/1.7.3"
+ },
+ "funding": [
+ {
+ "url": "https://packagist.com",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/composer",
+ "type": "github"
+ }
+ ],
+ "time": "2026-05-05T09:17:07+00:00"
+ },
+ {
+ "name": "composer/pcre",
+ "version": "3.4.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/composer/pcre.git",
+ "reference": "d5a341b3fb61f3001970940afb1d332968a183ed"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/composer/pcre/zipball/d5a341b3fb61f3001970940afb1d332968a183ed",
+ "reference": "d5a341b3fb61f3001970940afb1d332968a183ed",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^7.4 || ^8.0"
+ },
+ "conflict": {
+ "phpstan/phpstan": "<2.2.2"
+ },
+ "require-dev": {
+ "phpstan/phpstan": "^2",
+ "phpstan/phpstan-deprecation-rules": "^2",
+ "phpstan/phpstan-strict-rules": "^2",
+ "phpunit/phpunit": "^9"
+ },
+ "type": "library",
+ "extra": {
+ "phpstan": {
+ "includes": [
+ "extension.neon"
+ ]
+ },
+ "branch-alias": {
+ "dev-main": "3.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Composer\\Pcre\\": "src"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Jordi Boggiano",
+ "email": "j.boggiano@seld.be",
+ "homepage": "http://seld.be"
+ }
+ ],
+ "description": "PCRE wrapping library that offers type-safe preg_* replacements.",
+ "keywords": [
+ "PCRE",
+ "preg",
+ "regex",
+ "regular expression"
+ ],
+ "support": {
+ "issues": "https://github.com/composer/pcre/issues",
+ "source": "https://github.com/composer/pcre/tree/3.4.0"
+ },
+ "funding": [
+ {
+ "url": "https://packagist.com",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/composer",
+ "type": "github"
+ }
+ ],
+ "time": "2026-06-07T11:47:49+00:00"
+ },
+ {
+ "name": "composer/xdebug-handler",
+ "version": "3.0.5",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/composer/xdebug-handler.git",
+ "reference": "6c1925561632e83d60a44492e0b344cf48ab85ef"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/composer/xdebug-handler/zipball/6c1925561632e83d60a44492e0b344cf48ab85ef",
+ "reference": "6c1925561632e83d60a44492e0b344cf48ab85ef",
+ "shasum": ""
+ },
+ "require": {
+ "composer/pcre": "^1 || ^2 || ^3",
+ "php": "^7.2.5 || ^8.0",
+ "psr/log": "^1 || ^2 || ^3"
+ },
+ "require-dev": {
+ "phpstan/phpstan": "^1.0",
+ "phpstan/phpstan-strict-rules": "^1.1",
+ "phpunit/phpunit": "^8.5 || ^9.6 || ^10.5"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Composer\\XdebugHandler\\": "src"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "John Stevenson",
+ "email": "john-stevenson@blueyonder.co.uk"
+ }
+ ],
+ "description": "Restarts a process without Xdebug.",
+ "keywords": [
+ "Xdebug",
+ "performance"
+ ],
+ "support": {
+ "irc": "ircs://irc.libera.chat:6697/composer",
+ "issues": "https://github.com/composer/xdebug-handler/issues",
+ "source": "https://github.com/composer/xdebug-handler/tree/3.0.5"
+ },
+ "funding": [
+ {
+ "url": "https://packagist.com",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/composer",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/composer/composer",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2024-05-06T16:37:16+00:00"
+ },
+ {
+ "name": "dealerdirect/phpcodesniffer-composer-installer",
+ "version": "v1.2.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/PHPCSStandards/composer-installer.git",
+ "reference": "963f0c67bffde0eac41b56be71ac0e8ba132f0bd"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/PHPCSStandards/composer-installer/zipball/963f0c67bffde0eac41b56be71ac0e8ba132f0bd",
+ "reference": "963f0c67bffde0eac41b56be71ac0e8ba132f0bd",
+ "shasum": ""
+ },
+ "require": {
+ "composer-plugin-api": "^2.2",
+ "php": ">=5.4",
+ "squizlabs/php_codesniffer": "^3.1.0 || ^4.0"
+ },
+ "require-dev": {
+ "composer/composer": "^2.2",
+ "ext-json": "*",
+ "ext-zip": "*",
+ "php-parallel-lint/php-parallel-lint": "^1.4.0",
+ "phpcompatibility/php-compatibility": "^9.0 || ^10.0.0@dev",
+ "yoast/phpunit-polyfills": "^1.0"
+ },
+ "type": "composer-plugin",
+ "extra": {
+ "class": "PHPCSStandards\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\Plugin"
+ },
+ "autoload": {
+ "psr-4": {
+ "PHPCSStandards\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Franck Nijhof",
+ "email": "opensource@frenck.dev",
+ "homepage": "https://frenck.dev",
+ "role": "Open source developer"
+ },
+ {
+ "name": "Contributors",
+ "homepage": "https://github.com/PHPCSStandards/composer-installer/graphs/contributors"
+ }
+ ],
+ "description": "PHP_CodeSniffer Standards Composer Installer Plugin",
+ "keywords": [
+ "PHPCodeSniffer",
+ "PHP_CodeSniffer",
+ "code quality",
+ "codesniffer",
+ "composer",
+ "installer",
+ "phpcbf",
+ "phpcs",
+ "plugin",
+ "qa",
+ "quality",
+ "standard",
+ "standards",
+ "style guide",
+ "stylecheck",
+ "tests"
+ ],
+ "support": {
+ "issues": "https://github.com/PHPCSStandards/composer-installer/issues",
+ "security": "https://github.com/PHPCSStandards/composer-installer/security/policy",
+ "source": "https://github.com/PHPCSStandards/composer-installer"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/PHPCSStandards",
+ "type": "github"
+ },
+ {
+ "url": "https://github.com/jrfnl",
+ "type": "github"
+ },
+ {
+ "url": "https://opencollective.com/php_codesniffer",
+ "type": "open_collective"
+ },
+ {
+ "url": "https://thanks.dev/u/gh/phpcsstandards",
+ "type": "thanks_dev"
+ }
+ ],
+ "time": "2026-05-06T08:26:05+00:00"
+ },
+ {
+ "name": "dg/bypass-finals",
+ "version": "v1.11.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/dg/bypass-finals.git",
+ "reference": "b21595bdd1937e9ac912d68380dc85a65d77285f"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/dg/bypass-finals/zipball/b21595bdd1937e9ac912d68380dc85a65d77285f",
+ "reference": "b21595bdd1937e9ac912d68380dc85a65d77285f",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.2"
+ },
+ "require-dev": {
+ "nette/phpstan-rules": "^1.0",
+ "nette/tester": "^2.6",
+ "phpstan/extension-installer": "^1.4",
+ "phpstan/phpstan": "^2.2"
+ },
+ "type": "library",
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause",
+ "GPL-2.0-only",
+ "GPL-3.0-only"
+ ],
+ "authors": [
+ {
+ "name": "David Grudl",
+ "homepage": "https://davidgrudl.com"
+ }
+ ],
+ "description": "Removes final keyword from source code on-the-fly and allows mocking of final methods and classes",
+ "keywords": [
+ "finals",
+ "mocking",
+ "phpunit",
+ "testing",
+ "unit"
+ ],
+ "support": {
+ "issues": "https://github.com/dg/bypass-finals/issues",
+ "source": "https://github.com/dg/bypass-finals/tree/v1.11.0"
+ },
+ "time": "2026-07-24T12:24:07+00:00"
+ },
+ {
+ "name": "doctrine/deprecations",
+ "version": "1.1.6",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/doctrine/deprecations.git",
+ "reference": "d4fe3e6fd9bb9e72557a19674f44d8ac7db4c6ca"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/doctrine/deprecations/zipball/d4fe3e6fd9bb9e72557a19674f44d8ac7db4c6ca",
+ "reference": "d4fe3e6fd9bb9e72557a19674f44d8ac7db4c6ca",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^7.1 || ^8.0"
+ },
+ "conflict": {
+ "phpunit/phpunit": "<=7.5 || >=14"
+ },
+ "require-dev": {
+ "doctrine/coding-standard": "^9 || ^12 || ^14",
+ "phpstan/phpstan": "1.4.10 || 2.1.30",
+ "phpstan/phpstan-phpunit": "^1.0 || ^2",
+ "phpunit/phpunit": "^7.5 || ^8.5 || ^9.6 || ^10.5 || ^11.5 || ^12.4 || ^13.0",
+ "psr/log": "^1 || ^2 || ^3"
+ },
+ "suggest": {
+ "psr/log": "Allows logging deprecations via PSR-3 logger implementation"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Doctrine\\Deprecations\\": "src"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "description": "A small layer on top of trigger_error(E_USER_DEPRECATED) or PSR-3 logging with options to disable all deprecations or selectively for packages.",
+ "homepage": "https://www.doctrine-project.org/",
+ "support": {
+ "issues": "https://github.com/doctrine/deprecations/issues",
+ "source": "https://github.com/doctrine/deprecations/tree/1.1.6"
+ },
+ "time": "2026-02-07T07:09:04+00:00"
+ },
+ {
+ "name": "fakerphp/faker",
+ "version": "v1.24.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/FakerPHP/Faker.git",
+ "reference": "e0ee18eb1e6dc3cda3ce9fd97e5a0689a88a64b5"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/FakerPHP/Faker/zipball/e0ee18eb1e6dc3cda3ce9fd97e5a0689a88a64b5",
+ "reference": "e0ee18eb1e6dc3cda3ce9fd97e5a0689a88a64b5",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^7.4 || ^8.0",
+ "psr/container": "^1.0 || ^2.0",
+ "symfony/deprecation-contracts": "^2.2 || ^3.0"
+ },
+ "conflict": {
+ "fzaninotto/faker": "*"
+ },
+ "require-dev": {
+ "bamarni/composer-bin-plugin": "^1.4.1",
+ "doctrine/persistence": "^1.3 || ^2.0",
+ "ext-intl": "*",
+ "phpunit/phpunit": "^9.5.26",
+ "symfony/phpunit-bridge": "^5.4.16"
+ },
+ "suggest": {
+ "doctrine/orm": "Required to use Faker\\ORM\\Doctrine",
+ "ext-curl": "Required by Faker\\Provider\\Image to download images.",
+ "ext-dom": "Required by Faker\\Provider\\HtmlLorem for generating random HTML.",
+ "ext-iconv": "Required by Faker\\Provider\\ru_RU\\Text::realText() for generating real Russian text.",
+ "ext-mbstring": "Required for multibyte Unicode string functionality."
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Faker\\": "src/Faker/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "François Zaninotto"
+ }
+ ],
+ "description": "Faker is a PHP library that generates fake data for you.",
+ "keywords": [
+ "data",
+ "faker",
+ "fixtures"
+ ],
+ "support": {
+ "issues": "https://github.com/FakerPHP/Faker/issues",
+ "source": "https://github.com/FakerPHP/Faker/tree/v1.24.1"
+ },
+ "time": "2024-11-21T13:46:39+00:00"
+ },
+ {
+ "name": "fidry/cpu-core-counter",
+ "version": "1.3.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/theofidry/cpu-core-counter.git",
+ "reference": "db9508f7b1474469d9d3c53b86f817e344732678"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/theofidry/cpu-core-counter/zipball/db9508f7b1474469d9d3c53b86f817e344732678",
+ "reference": "db9508f7b1474469d9d3c53b86f817e344732678",
+ "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": "^2.0",
+ "phpstan/phpstan-deprecation-rules": "^2.0.0",
+ "phpstan/phpstan-phpunit": "^2.0",
+ "phpstan/phpstan-strict-rules": "^2.0",
+ "phpunit/phpunit": "^8.5.31 || ^9.5.26",
+ "webmozarts/strict-phpunit": "^7.5"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Fidry\\CpuCoreCounter\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Théo FIDRY",
+ "email": "theo.fidry@gmail.com"
+ }
+ ],
+ "description": "Tiny utility to get the number of CPU cores.",
+ "keywords": [
+ "CPU",
+ "core"
+ ],
+ "support": {
+ "issues": "https://github.com/theofidry/cpu-core-counter/issues",
+ "source": "https://github.com/theofidry/cpu-core-counter/tree/1.3.0"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/theofidry",
+ "type": "github"
+ }
+ ],
+ "time": "2025-08-14T07:29:31+00:00"
+ },
+ {
+ "name": "filp/whoops",
+ "version": "2.18.4",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/filp/whoops.git",
+ "reference": "d2102955e48b9fd9ab24280a7ad12ed552752c4d"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/filp/whoops/zipball/d2102955e48b9fd9ab24280a7ad12ed552752c4d",
+ "reference": "d2102955e48b9fd9ab24280a7ad12ed552752c4d",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^7.1 || ^8.0",
+ "psr/log": "^1.0.1 || ^2.0 || ^3.0"
+ },
+ "require-dev": {
+ "mockery/mockery": "^1.0",
+ "phpunit/phpunit": "^7.5.20 || ^8.5.8 || ^9.3.3",
+ "symfony/var-dumper": "^4.0 || ^5.0"
+ },
+ "suggest": {
+ "symfony/var-dumper": "Pretty print complex values better with var-dumper available",
+ "whoops/soap": "Formats errors as SOAP responses"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.7-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Whoops\\": "src/Whoops/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Filipe Dobreira",
+ "homepage": "https://github.com/filp",
+ "role": "Developer"
+ }
+ ],
+ "description": "php error handling for cool kids",
+ "homepage": "https://filp.github.io/whoops/",
+ "keywords": [
+ "error",
+ "exception",
+ "handling",
+ "library",
+ "throwable",
+ "whoops"
+ ],
+ "support": {
+ "issues": "https://github.com/filp/whoops/issues",
+ "source": "https://github.com/filp/whoops/tree/2.18.4"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/denis-sokolov",
+ "type": "github"
+ }
+ ],
+ "time": "2025-08-08T12:00:00+00:00"
+ },
+ {
+ "name": "hamcrest/hamcrest-php",
+ "version": "v2.1.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/hamcrest/hamcrest-php.git",
+ "reference": "f8b1c0173b22fa6ec77a81fe63e5b01eba7e6487"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/hamcrest/hamcrest-php/zipball/f8b1c0173b22fa6ec77a81fe63e5b01eba7e6487",
+ "reference": "f8b1c0173b22fa6ec77a81fe63e5b01eba7e6487",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^7.4|^8.0"
+ },
+ "replace": {
+ "cordoval/hamcrest-php": "*",
+ "davedevelopment/hamcrest-php": "*",
+ "kodova/hamcrest-php": "*"
+ },
+ "require-dev": {
+ "phpunit/php-file-iterator": "^1.4 || ^2.0 || ^3.0",
+ "phpunit/phpunit": "^4.8.36 || ^5.7 || ^6.5 || ^7.0 || ^8.0 || ^9.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.1-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "hamcrest"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "description": "This is the PHP port of Hamcrest Matchers",
+ "keywords": [
+ "test"
+ ],
+ "support": {
+ "issues": "https://github.com/hamcrest/hamcrest-php/issues",
+ "source": "https://github.com/hamcrest/hamcrest-php/tree/v2.1.1"
+ },
+ "time": "2025-04-30T06:54:44+00:00"
+ },
+ {
+ "name": "hotmeteor/spectator",
+ "version": "v3.0.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/hotmeteor/spectator.git",
+ "reference": "429da34ebba351329c4ca3ba62c9c5b621f9b6fb"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/hotmeteor/spectator/zipball/429da34ebba351329c4ca3ba62c9c5b621f9b6fb",
+ "reference": "429da34ebba351329c4ca3ba62c9c5b621f9b6fb",
+ "shasum": ""
+ },
+ "require": {
+ "cebe/php-openapi": "^1.8",
+ "ext-json": "*",
+ "laravel/framework": ">=12.0",
+ "opis/json-schema": "^2.3",
+ "php": "^8.3"
+ },
+ "require-dev": {
+ "larastan/larastan": ">=3.0",
+ "laravel/pint": "^1.13",
+ "nunomaduro/collision": ">=8.0",
+ "orchestra/testbench": ">=10.0",
+ "phpunit/phpunit": "^11.0"
+ },
+ "type": "library",
+ "extra": {
+ "laravel": {
+ "providers": [
+ "Spectator\\SpectatorServiceProvider"
+ ]
+ },
+ "branch-alias": {
+ "dev-master": "3.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Spectator\\": "src"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Adam Campbell",
+ "email": "adam@hotmeteor.com"
+ }
+ ],
+ "description": "Testing helpers for your OpenAPI spec",
+ "keywords": [
+ "laravel",
+ "openapi",
+ "spectator",
+ "testing"
+ ],
+ "support": {
+ "issues": "https://github.com/hotmeteor/spectator/issues",
+ "source": "https://github.com/hotmeteor/spectator/tree/v3.0.2"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/bastien-phi",
+ "type": "github"
+ },
+ {
+ "url": "https://github.com/hotmeteor",
+ "type": "github"
+ },
+ {
+ "url": "https://github.com/jarrodparkes",
+ "type": "github"
+ }
+ ],
+ "time": "2026-05-01T00:14:25+00:00"
+ },
+ {
+ "name": "iamcal/sql-parser",
+ "version": "v0.7",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/iamcal/SQLParser.git",
+ "reference": "610392f38de49a44dab08dc1659960a29874c4b8"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/iamcal/SQLParser/zipball/610392f38de49a44dab08dc1659960a29874c4b8",
+ "reference": "610392f38de49a44dab08dc1659960a29874c4b8",
+ "shasum": ""
+ },
+ "require-dev": {
+ "php-coveralls/php-coveralls": "^1.0",
+ "phpunit/phpunit": "^5|^6|^7|^8|^9"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "iamcal\\": "src"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Cal Henderson",
+ "email": "cal@iamcal.com"
+ }
+ ],
+ "description": "MySQL schema parser",
+ "support": {
+ "issues": "https://github.com/iamcal/SQLParser/issues",
+ "source": "https://github.com/iamcal/SQLParser/tree/v0.7"
+ },
+ "time": "2026-01-28T22:20:33+00:00"
+ },
+ {
+ "name": "justinrainbow/json-schema",
+ "version": "6.10.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/jsonrainbow/json-schema.git",
+ "reference": "8b1308a9d7bdbdb20ce87ef920f82b4564bb2d33"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/jsonrainbow/json-schema/zipball/8b1308a9d7bdbdb20ce87ef920f82b4564bb2d33",
+ "reference": "8b1308a9d7bdbdb20ce87ef920f82b4564bb2d33",
+ "shasum": ""
+ },
+ "require": {
+ "ext-json": "*",
+ "marc-mabe/php-enum": "^4.4",
+ "php": "^7.2 || ^8.0"
+ },
+ "require-dev": {
+ "friendsofphp/php-cs-fixer": "3.3.0",
+ "json-schema/json-schema-test-suite": "dev-main",
+ "marc-mabe/php-enum-phpstan": "^2.0",
+ "phpspec/prophecy": "^1.19",
+ "phpstan/phpstan": "^1.12",
+ "phpunit/phpunit": "^8.5"
+ },
+ "bin": [
+ "bin/validate-json"
+ ],
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "6.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "JsonSchema\\": "src/JsonSchema/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Bruno Prieto Reis",
+ "email": "bruno.p.reis@gmail.com"
+ },
+ {
+ "name": "Justin Rainbow",
+ "email": "justin.rainbow@gmail.com"
+ },
+ {
+ "name": "Igor Wiedler",
+ "email": "igor@wiedler.ch"
+ },
+ {
+ "name": "Robert Schönthal",
+ "email": "seroscho@googlemail.com"
+ }
+ ],
+ "description": "A library to validate a json schema.",
+ "homepage": "https://github.com/jsonrainbow/json-schema",
+ "keywords": [
+ "json",
+ "schema"
+ ],
+ "support": {
+ "issues": "https://github.com/jsonrainbow/json-schema/issues",
+ "source": "https://github.com/jsonrainbow/json-schema/tree/6.10.0"
+ },
+ "time": "2026-06-16T20:50:26+00:00"
+ },
+ {
+ "name": "larastan/larastan",
+ "version": "v3.10.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/larastan/larastan.git",
+ "reference": "2970f83398154178a739609c244577267c7ee8eb"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/larastan/larastan/zipball/2970f83398154178a739609c244577267c7ee8eb",
+ "reference": "2970f83398154178a739609c244577267c7ee8eb",
+ "shasum": ""
+ },
+ "require": {
+ "ext-json": "*",
+ "iamcal/sql-parser": "^0.7.0",
+ "illuminate/console": "^11.44.2 || ^12.4.1 || ^13",
+ "illuminate/container": "^11.44.2 || ^12.4.1 || ^13",
+ "illuminate/contracts": "^11.44.2 || ^12.4.1 || ^13",
+ "illuminate/database": "^11.44.2 || ^12.4.1 || ^13",
+ "illuminate/http": "^11.44.2 || ^12.4.1 || ^13",
+ "illuminate/pipeline": "^11.44.2 || ^12.4.1 || ^13",
+ "illuminate/support": "^11.44.2 || ^12.4.1 || ^13",
+ "php": "^8.2",
+ "phpstan/phpstan": "^2.2.0"
+ },
+ "require-dev": {
+ "doctrine/coding-standard": "^14",
+ "laravel/framework": "^11.44.2 || ^12.7.2 || ^13",
+ "mockery/mockery": "^1.6.12",
+ "nikic/php-parser": "^5.4",
+ "orchestra/canvas": "^v9.2.2 || ^10.0.1 || ^11",
+ "orchestra/testbench-core": "^9.12.0 || ^10.1 || ^11",
+ "phpstan/phpstan-deprecation-rules": "^2.0.1",
+ "phpunit/phpunit": "^10.5.35 || ^11.5.15 || ^12.5.8 || ^13.1.8"
+ },
+ "suggest": {
+ "orchestra/testbench": "Using Larastan for analysing a package needs Testbench",
+ "phpmyadmin/sql-parser": "Install to enable Larastan's optional phpMyAdmin-based SQL parser automatically"
+ },
+ "type": "phpstan-extension",
+ "extra": {
+ "phpstan": {
+ "includes": [
+ "extension.neon"
+ ]
+ },
+ "branch-alias": {
+ "dev-master": "3.0-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Larastan\\Larastan\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Can Vural",
+ "email": "can9119@gmail.com"
+ }
+ ],
+ "description": "Larastan - Discover bugs in your code without running it. A phpstan/phpstan extension for Laravel",
+ "keywords": [
+ "PHPStan",
+ "code analyse",
+ "code analysis",
+ "larastan",
+ "laravel",
+ "package",
+ "php",
+ "static analysis"
+ ],
+ "support": {
+ "issues": "https://github.com/larastan/larastan/issues",
+ "source": "https://github.com/larastan/larastan/tree/v3.10.0"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/canvural",
+ "type": "github"
+ }
+ ],
+ "time": "2026-05-28T08:00:58+00:00"
+ },
+ {
+ "name": "laravel/agent-detector",
+ "version": "v2.0.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/laravel/agent-detector.git",
+ "reference": "90694b9256099591cf9e55d08c18ba7a00bf099f"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/laravel/agent-detector/zipball/90694b9256099591cf9e55d08c18ba7a00bf099f",
+ "reference": "90694b9256099591cf9e55d08c18ba7a00bf099f",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^8.2.0"
+ },
+ "require-dev": {
+ "laravel/pint": "^1.24.0",
+ "pestphp/pest": "^3.8.5|^4.1.0",
+ "pestphp/pest-plugin-type-coverage": "^3.0|^4.0.2",
+ "phpstan/phpstan": "^2.1.26",
+ "rector/rector": "^2.1.7",
+ "symfony/var-dumper": "^7.3.3"
+ },
+ "type": "library",
+ "autoload": {
+ "files": [
+ "src/functions.php"
+ ],
+ "psr-4": {
+ "Laravel\\AgentDetector\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Taylor Otwell",
+ "email": "taylor@laravel.com"
+ }
+ ],
+ "description": "Detect if code is running in an AI agent or automated development environment",
+ "homepage": "https://github.com/laravel/agent-detector",
+ "keywords": [
+ "Agent",
+ "ai",
+ "automation",
+ "claude",
+ "cursor",
+ "detection",
+ "devin",
+ "php"
+ ],
+ "support": {
+ "issues": "https://github.com/laravel/agent-detector/issues",
+ "source": "https://github.com/laravel/agent-detector"
+ },
+ "time": "2026-04-29T18:32:34+00:00"
+ },
+ {
+ "name": "laravel/pail",
+ "version": "v1.2.7",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/laravel/pail.git",
+ "reference": "2f7d27dada8effc48b8c424445a69cca7007daaa"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/laravel/pail/zipball/2f7d27dada8effc48b8c424445a69cca7007daaa",
+ "reference": "2f7d27dada8effc48b8c424445a69cca7007daaa",
+ "shasum": ""
+ },
+ "require": {
+ "ext-mbstring": "*",
+ "illuminate/console": "^10.24|^11.0|^12.0|^13.0",
+ "illuminate/contracts": "^10.24|^11.0|^12.0|^13.0",
+ "illuminate/log": "^10.24|^11.0|^12.0|^13.0",
+ "illuminate/process": "^10.24|^11.0|^12.0|^13.0",
+ "illuminate/support": "^10.24|^11.0|^12.0|^13.0",
+ "nunomaduro/termwind": "^1.15|^2.0",
+ "php": "^8.2",
+ "symfony/console": "^6.0|^7.0|^8.0"
+ },
+ "require-dev": {
+ "laravel/framework": "^10.24|^11.0|^12.0|^13.0",
+ "laravel/pint": "^1.13",
+ "orchestra/testbench-core": "^8.13|^9.17|^10.8|^11.0",
+ "pestphp/pest": "^2.20|^3.0|^4.0",
+ "pestphp/pest-plugin-type-coverage": "^2.3|^3.0|^4.0",
+ "phpstan/phpstan": "^1.12.27",
+ "symfony/var-dumper": "^6.3|^7.0|^8.0",
+ "symfony/yaml": "^6.3|^7.0|^8.0"
+ },
+ "type": "library",
+ "extra": {
+ "laravel": {
+ "providers": [
+ "Laravel\\Pail\\PailServiceProvider"
+ ]
+ },
+ "branch-alias": {
+ "dev-main": "1.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Laravel\\Pail\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Taylor Otwell",
+ "email": "taylor@laravel.com"
+ },
+ {
+ "name": "Nuno Maduro",
+ "email": "enunomaduro@gmail.com"
+ }
+ ],
+ "description": "Easily delve into your Laravel application's log files directly from the command line.",
+ "homepage": "https://github.com/laravel/pail",
+ "keywords": [
+ "dev",
+ "laravel",
+ "logs",
+ "php",
+ "tail"
+ ],
+ "support": {
+ "issues": "https://github.com/laravel/pail/issues",
+ "source": "https://github.com/laravel/pail"
+ },
+ "time": "2026-05-20T22:24:57+00:00"
+ },
+ {
+ "name": "laravel/pao",
+ "version": "v1.1.3",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/laravel/pao.git",
+ "reference": "322f22095f3639551b64db9a13dfd8ab09c8206b"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/laravel/pao/zipball/322f22095f3639551b64db9a13dfd8ab09c8206b",
+ "reference": "322f22095f3639551b64db9a13dfd8ab09c8206b",
+ "shasum": ""
+ },
+ "require": {
+ "laravel/agent-detector": "^2.0.2",
+ "php": "^8.3"
+ },
+ "conflict": {
+ "laravel/framework": "<12.0.0",
+ "nunomaduro/collision": "<8.9.3",
+ "pestphp/pest": "<4.6.3 || >=6.0.0",
+ "phpunit/phpunit": "<12.5.23 || >=13.0.0 <13.1.7 || >=14.0.0"
+ },
+ "require-dev": {
+ "brianium/paratest": "^7.23.0",
+ "laravel/pint": "^1.30.0",
+ "orchestra/testbench": "^10.11.0 || ^11.1.0",
+ "pestphp/pest": "^4.7.2 || ^5.0.1",
+ "pestphp/pest-plugin-type-coverage": "^4.0.4 || ^5.0.0",
+ "phpstan/phpstan": "^2.2.7",
+ "rector/rector": "^2.5.8",
+ "symfony/process": "^7.4.8 || ^8.1.0",
+ "symfony/var-dumper": "^7.4.8 || ^8.1.2"
+ },
+ "type": "library",
+ "extra": {
+ "pest": {
+ "plugins": [
+ "Laravel\\Pao\\Drivers\\Pest\\Plugin"
+ ]
+ },
+ "laravel": {
+ "providers": [
+ "Laravel\\Pao\\Laravel\\ServiceProvider"
+ ]
+ }
+ },
+ "autoload": {
+ "files": [
+ "src/Autoload.php"
+ ],
+ "psr-4": {
+ "Laravel\\Pao\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Taylor Otwell",
+ "email": "taylor@laravel.com"
+ }
+ ],
+ "description": "Agent-optimized output for PHP testing tools",
+ "keywords": [
+ "Agent",
+ "PHPStan",
+ "ai",
+ "dev",
+ "paratest",
+ "pest",
+ "php",
+ "phpunit",
+ "rector",
+ "testing"
+ ],
+ "support": {
+ "issues": "https://github.com/laravel/pao/issues",
+ "source": "https://github.com/laravel/pao"
+ },
+ "time": "2026-07-29T18:38:14+00:00"
+ },
+ {
+ "name": "laravel/pint",
+ "version": "v1.30.4",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/laravel/pint.git",
+ "reference": "a96cb6eee2961905d2fce7207aefb80945bf6b28"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/laravel/pint/zipball/a96cb6eee2961905d2fce7207aefb80945bf6b28",
+ "reference": "a96cb6eee2961905d2fce7207aefb80945bf6b28",
+ "shasum": ""
+ },
+ "require": {
+ "ext-json": "*",
+ "ext-mbstring": "*",
+ "ext-tokenizer": "*",
+ "ext-xml": "*",
+ "php": "^8.2.0"
+ },
+ "require-dev": {
+ "composer/semver": "^3.4.4",
+ "friendsofphp/php-cs-fixer": "^3.95.18",
+ "illuminate/view": "^12.65.0",
+ "larastan/larastan": "^3.10.0",
+ "laravel-zero/framework": "^12.1.0",
+ "laravel/agent-detector": "^2.0.2",
+ "laravel/prompts": "^0.3.22",
+ "mockery/mockery": "^1.6.12",
+ "nunomaduro/termwind": "^2.4.0",
+ "pestphp/pest": "^3.8.7"
+ },
+ "bin": [
+ "builds/pint"
+ ],
+ "type": "project",
+ "autoload": {
+ "psr-4": {
+ "App\\": "app/",
+ "Database\\Seeders\\": "database/seeders/",
+ "Database\\Factories\\": "database/factories/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Nuno Maduro",
+ "email": "enunomaduro@gmail.com"
+ }
+ ],
+ "description": "An opinionated code formatter for PHP.",
+ "homepage": "https://laravel.com",
+ "keywords": [
+ "dev",
+ "format",
+ "formatter",
+ "lint",
+ "linter",
+ "php"
+ ],
+ "support": {
+ "issues": "https://github.com/laravel/pint/issues",
+ "source": "https://github.com/laravel/pint"
+ },
+ "time": "2026-08-05T16:47:22+00:00"
+ },
+ {
+ "name": "marc-mabe/php-enum",
+ "version": "v4.7.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/marc-mabe/php-enum.git",
+ "reference": "bb426fcdd65c60fb3638ef741e8782508fda7eef"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/marc-mabe/php-enum/zipball/bb426fcdd65c60fb3638ef741e8782508fda7eef",
+ "reference": "bb426fcdd65c60fb3638ef741e8782508fda7eef",
+ "shasum": ""
+ },
+ "require": {
+ "ext-reflection": "*",
+ "php": "^7.1 | ^8.0"
+ },
+ "require-dev": {
+ "phpbench/phpbench": "^0.16.10 || ^1.0.4",
+ "phpstan/phpstan": "^1.3.1",
+ "phpunit/phpunit": "^7.5.20 | ^8.5.22 | ^9.5.11",
+ "vimeo/psalm": "^4.17.0 | ^5.26.1"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-3.x": "3.2-dev",
+ "dev-master": "4.7-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "MabeEnum\\": "src/"
+ },
+ "classmap": [
+ "stubs/Stringable.php"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Marc Bennewitz",
+ "email": "dev@mabe.berlin",
+ "homepage": "https://mabe.berlin/",
+ "role": "Lead"
+ }
+ ],
+ "description": "Simple and fast implementation of enumerations with native PHP",
+ "homepage": "https://github.com/marc-mabe/php-enum",
+ "keywords": [
+ "enum",
+ "enum-map",
+ "enum-set",
+ "enumeration",
+ "enumerator",
+ "enummap",
+ "enumset",
+ "map",
+ "set",
+ "type",
+ "type-hint",
+ "typehint"
+ ],
+ "support": {
+ "issues": "https://github.com/marc-mabe/php-enum/issues",
+ "source": "https://github.com/marc-mabe/php-enum/tree/v4.7.2"
+ },
+ "time": "2025-09-14T11:18:39+00:00"
+ },
+ {
+ "name": "mockery/mockery",
+ "version": "1.6.12",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/mockery/mockery.git",
+ "reference": "1f4efdd7d3beafe9807b08156dfcb176d18f1699"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/mockery/mockery/zipball/1f4efdd7d3beafe9807b08156dfcb176d18f1699",
+ "reference": "1f4efdd7d3beafe9807b08156dfcb176d18f1699",
+ "shasum": ""
+ },
+ "require": {
+ "hamcrest/hamcrest-php": "^2.0.1",
+ "lib-pcre": ">=7.0",
+ "php": ">=7.3"
+ },
+ "conflict": {
+ "phpunit/phpunit": "<8.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^8.5 || ^9.6.17",
+ "symplify/easy-coding-standard": "^12.1.14"
+ },
+ "type": "library",
+ "autoload": {
+ "files": [
+ "library/helpers.php",
+ "library/Mockery.php"
+ ],
+ "psr-4": {
+ "Mockery\\": "library/Mockery"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Pádraic Brady",
+ "email": "padraic.brady@gmail.com",
+ "homepage": "https://github.com/padraic",
+ "role": "Author"
+ },
+ {
+ "name": "Dave Marshall",
+ "email": "dave.marshall@atstsolutions.co.uk",
+ "homepage": "https://davedevelopment.co.uk",
+ "role": "Developer"
+ },
+ {
+ "name": "Nathanael Esayeas",
+ "email": "nathanael.esayeas@protonmail.com",
+ "homepage": "https://github.com/ghostwriter",
+ "role": "Lead Developer"
+ }
+ ],
+ "description": "Mockery is a simple yet flexible PHP mock object framework",
+ "homepage": "https://github.com/mockery/mockery",
+ "keywords": [
+ "BDD",
+ "TDD",
+ "library",
+ "mock",
+ "mock objects",
+ "mockery",
+ "stub",
+ "test",
+ "test double",
+ "testing"
+ ],
+ "support": {
+ "docs": "https://docs.mockery.io/",
+ "issues": "https://github.com/mockery/mockery/issues",
+ "rss": "https://github.com/mockery/mockery/releases.atom",
+ "security": "https://github.com/mockery/mockery/security/advisories",
+ "source": "https://github.com/mockery/mockery"
+ },
+ "time": "2024-05-16T03:13:13+00:00"
+ },
+ {
+ "name": "myclabs/deep-copy",
+ "version": "1.13.4",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/myclabs/DeepCopy.git",
+ "reference": "07d290f0c47959fd5eed98c95ee5602db07e0b6a"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/07d290f0c47959fd5eed98c95ee5602db07e0b6a",
+ "reference": "07d290f0c47959fd5eed98c95ee5602db07e0b6a",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^7.1 || ^8.0"
+ },
+ "conflict": {
+ "doctrine/collections": "<1.6.8",
+ "doctrine/common": "<2.13.3 || >=3 <3.2.2"
+ },
+ "require-dev": {
+ "doctrine/collections": "^1.6.8",
+ "doctrine/common": "^2.13.3 || ^3.2.2",
+ "phpspec/prophecy": "^1.10",
+ "phpunit/phpunit": "^7.5.20 || ^8.5.23 || ^9.5.13"
+ },
+ "type": "library",
+ "autoload": {
+ "files": [
+ "src/DeepCopy/deep_copy.php"
+ ],
+ "psr-4": {
+ "DeepCopy\\": "src/DeepCopy/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "description": "Create deep copies (clones) of your objects",
+ "keywords": [
+ "clone",
+ "copy",
+ "duplicate",
+ "object",
+ "object graph"
+ ],
+ "support": {
+ "issues": "https://github.com/myclabs/DeepCopy/issues",
+ "source": "https://github.com/myclabs/DeepCopy/tree/1.13.4"
+ },
+ "funding": [
+ {
+ "url": "https://tidelift.com/funding/github/packagist/myclabs/deep-copy",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2025-08-01T08:46:24+00:00"
+ },
+ {
+ "name": "nikic/php-parser",
+ "version": "v5.8.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/nikic/PHP-Parser.git",
+ "reference": "044a6a392ff8ad0d61f14370a5fbbd0a0107152f"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/044a6a392ff8ad0d61f14370a5fbbd0a0107152f",
+ "reference": "044a6a392ff8ad0d61f14370a5fbbd0a0107152f",
+ "shasum": ""
+ },
+ "require": {
+ "ext-json": "*",
+ "ext-tokenizer": "*",
+ "php": ">=7.4"
+ },
+ "require-dev": {
+ "ircmaxell/php-yacc": "^0.0.7",
+ "phpunit/phpunit": "^9.0"
+ },
+ "bin": [
+ "bin/php-parse"
+ ],
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "5.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "PhpParser\\": "lib/PhpParser"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Nikita Popov"
+ }
+ ],
+ "description": "A PHP parser written in PHP",
+ "keywords": [
+ "parser",
+ "php"
+ ],
+ "support": {
+ "issues": "https://github.com/nikic/PHP-Parser/issues",
+ "source": "https://github.com/nikic/PHP-Parser/tree/v5.8.0"
+ },
+ "time": "2026-07-04T14:30:18+00:00"
+ },
+ {
+ "name": "nunomaduro/collision",
+ "version": "v8.9.5",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/nunomaduro/collision.git",
+ "reference": "fb53eacd509a1d303858e2d20cfebf2d630254ec"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/nunomaduro/collision/zipball/fb53eacd509a1d303858e2d20cfebf2d630254ec",
+ "reference": "fb53eacd509a1d303858e2d20cfebf2d630254ec",
+ "shasum": ""
+ },
+ "require": {
+ "filp/whoops": "^2.18.4",
+ "nunomaduro/termwind": "^2.4.0",
+ "php": "^8.2.0",
+ "symfony/console": "^7.4.14 || ^8.1.1"
+ },
+ "conflict": {
+ "laravel/framework": "<11.48.0 || >=14.0.0",
+ "phpunit/phpunit": "<11.5.50 || >=14.0.0"
+ },
+ "require-dev": {
+ "brianium/paratest": "^7.8.5",
+ "larastan/larastan": "^3.10.0",
+ "laravel/framework": "^11.48.0 || ^12.56.0 || ^13.20.0",
+ "laravel/pint": "^1.29.3",
+ "orchestra/testbench-core": "^9.12.0 || ^10.12.1 || ^11.3.5",
+ "pestphp/pest": "^3.8.5 || ^4.7.5 || ^5.0.0",
+ "sebastian/environment": "^7.2.1 || ^8.1.2 || ^9.3.2"
+ },
+ "type": "library",
+ "extra": {
+ "laravel": {
+ "providers": [
+ "NunoMaduro\\Collision\\Adapters\\Laravel\\CollisionServiceProvider"
+ ]
+ },
+ "branch-alias": {
+ "dev-8.x": "8.x-dev"
+ }
+ },
+ "autoload": {
+ "files": [
+ "./src/Adapters/Phpunit/Autoload.php"
+ ],
+ "psr-4": {
+ "NunoMaduro\\Collision\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Nuno Maduro",
+ "email": "enunomaduro@gmail.com"
+ }
+ ],
+ "description": "Cli error handling for console/command-line PHP applications.",
+ "keywords": [
+ "artisan",
+ "cli",
+ "command-line",
+ "console",
+ "dev",
+ "error",
+ "handling",
+ "laravel",
+ "laravel-zero",
+ "php",
+ "symfony"
+ ],
+ "support": {
+ "issues": "https://github.com/nunomaduro/collision/issues",
+ "source": "https://github.com/nunomaduro/collision"
+ },
+ "funding": [
+ {
+ "url": "https://www.paypal.com/paypalme/enunomaduro",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/nunomaduro",
+ "type": "github"
+ },
+ {
+ "url": "https://www.patreon.com/nunomaduro",
+ "type": "patreon"
+ }
+ ],
+ "time": "2026-07-15T19:09:14+00:00"
+ },
+ {
+ "name": "nunomaduro/mock-final-classes",
+ "version": "v1.2.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/nunomaduro/mock-final-classes.git",
+ "reference": "b13fc71acd9d6f1e2de8209217103cbd2035871f"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/nunomaduro/mock-final-classes/zipball/b13fc71acd9d6f1e2de8209217103cbd2035871f",
+ "reference": "b13fc71acd9d6f1e2de8209217103cbd2035871f",
+ "shasum": ""
+ },
+ "require": {
+ "dg/bypass-finals": "^1.1",
+ "php": "^7.1 || ^8.0"
+ },
+ "require-dev": {
+ "localheinz/phpstan-rules": "^0.10.0",
+ "phpstan/phpstan": "^0.11.8",
+ "phpstan/phpstan-strict-rules": "^0.11.1",
+ "phpunit/phpunit": "^7.0|^8.0|^9.3",
+ "thecodingmachine/phpstan-strict-rules": "^0.11.1"
+ },
+ "type": "library",
+ "autoload": {
+ "files": [
+ "autoload.php"
+ ],
+ "psr-4": {
+ "NunoMaduro\\MockFinalClasses\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Nuno Maduro",
+ "email": "enunomaduro@gmail.com"
+ }
+ ],
+ "description": "Allows mocking of final methods and classes in PHP.",
+ "keywords": [
+ "class",
+ "classes",
+ "final",
+ "mock",
+ "php",
+ "phpunit"
+ ],
+ "support": {
+ "issues": "https://github.com/nunomaduro/mock-final-classes/issues",
+ "source": "https://github.com/nunomaduro/mock-final-classes/tree/v1.2.0"
+ },
+ "funding": [
+ {
+ "url": "https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=66BYDWAT92N6L",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/nunomaduro",
+ "type": "github"
+ },
+ {
+ "url": "https://www.patreon.com/nunomaduro",
+ "type": "patreon"
+ }
+ ],
+ "time": "2023-05-14T23:33:16+00:00"
+ },
+ {
+ "name": "nunomaduro/pokio",
+ "version": "v1.0.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/nunomaduro/pokio.git",
+ "reference": "fc7884ebc5b0fabd6e267c0b4e6f750ba69cee5b"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/nunomaduro/pokio/zipball/fc7884ebc5b0fabd6e267c0b4e6f750ba69cee5b",
+ "reference": "fc7884ebc5b0fabd6e267c0b4e6f750ba69cee5b",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^8.3.0"
+ },
+ "conflict": {
+ "symplify/easy-parallel": "<11.2.2"
+ },
+ "require-dev": {
+ "laravel/pint": "^1.29.0",
+ "peckphp/peck": "^0.1.3",
+ "pestphp/pest": "^4.5.0",
+ "pestphp/pest-plugin-type-coverage": "^4.0.3",
+ "phpstan/phpstan": "^2.1.46",
+ "symfony/var-dumper": "^7.4.8 || ^8.0.8"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "0.1.x-dev"
+ }
+ },
+ "autoload": {
+ "files": [
+ "src/Functions.php"
+ ],
+ "psr-4": {
+ "Pokio\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Nuno Maduro",
+ "email": "enunomaduro@gmail.com"
+ }
+ ],
+ "description": "Pokio is a dead simple asynchronous API for PHP that just works",
+ "keywords": [
+ "asynchronous",
+ "library",
+ "php",
+ "pokio"
+ ],
+ "support": {
+ "issues": "https://github.com/nunomaduro/pokio/issues",
+ "source": "https://github.com/nunomaduro/pokio/tree/v1.0.1"
+ },
+ "funding": [
+ {
+ "url": "https://www.paypal.com/paypalme/enunomaduro",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/nunomaduro",
+ "type": "github"
+ },
+ {
+ "url": "https://www.patreon.com/nunomaduro",
+ "type": "patreon"
+ }
+ ],
+ "time": "2026-04-12T12:06:31+00:00"
+ },
+ {
+ "name": "opis/json-schema",
+ "version": "2.6.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/opis/json-schema.git",
+ "reference": "8458763e0dd0b6baa310e04f1829fc73da4e8c8a"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/opis/json-schema/zipball/8458763e0dd0b6baa310e04f1829fc73da4e8c8a",
+ "reference": "8458763e0dd0b6baa310e04f1829fc73da4e8c8a",
+ "shasum": ""
+ },
+ "require": {
+ "ext-json": "*",
+ "opis/string": "^2.1",
+ "opis/uri": "^1.0",
+ "php": "^7.4 || ^8.0"
+ },
+ "require-dev": {
+ "ext-bcmath": "*",
+ "ext-intl": "*",
+ "phpunit/phpunit": "^9.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Opis\\JsonSchema\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "Apache-2.0"
+ ],
+ "authors": [
+ {
+ "name": "Sorin Sarca",
+ "email": "sarca_sorin@hotmail.com"
+ },
+ {
+ "name": "Marius Sarca",
+ "email": "marius.sarca@gmail.com"
+ }
+ ],
+ "description": "Json Schema Validator for PHP",
+ "homepage": "https://opis.io/json-schema",
+ "keywords": [
+ "json",
+ "json-schema",
+ "schema",
+ "validation",
+ "validator"
+ ],
+ "support": {
+ "issues": "https://github.com/opis/json-schema/issues",
+ "source": "https://github.com/opis/json-schema/tree/2.6.0"
+ },
+ "time": "2025-10-17T12:46:48+00:00"
+ },
+ {
+ "name": "opis/string",
+ "version": "2.1.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/opis/string.git",
+ "reference": "3e4d2aaff518ac518530b89bb26ed40f4503635e"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/opis/string/zipball/3e4d2aaff518ac518530b89bb26ed40f4503635e",
+ "reference": "3e4d2aaff518ac518530b89bb26ed40f4503635e",
+ "shasum": ""
+ },
+ "require": {
+ "ext-iconv": "*",
+ "ext-json": "*",
+ "php": "^7.4 || ^8.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^9.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Opis\\String\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "Apache-2.0"
+ ],
+ "authors": [
+ {
+ "name": "Marius Sarca",
+ "email": "marius.sarca@gmail.com"
+ },
+ {
+ "name": "Sorin Sarca",
+ "email": "sarca_sorin@hotmail.com"
+ }
+ ],
+ "description": "Multibyte strings as objects",
+ "homepage": "https://opis.io/string",
+ "keywords": [
+ "multi-byte",
+ "opis",
+ "string",
+ "string manipulation",
+ "utf-8"
+ ],
+ "support": {
+ "issues": "https://github.com/opis/string/issues",
+ "source": "https://github.com/opis/string/tree/2.1.0"
+ },
+ "time": "2025-10-17T12:38:41+00:00"
+ },
+ {
+ "name": "opis/uri",
+ "version": "1.1.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/opis/uri.git",
+ "reference": "0f3ca49ab1a5e4a6681c286e0b2cc081b93a7d5a"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/opis/uri/zipball/0f3ca49ab1a5e4a6681c286e0b2cc081b93a7d5a",
+ "reference": "0f3ca49ab1a5e4a6681c286e0b2cc081b93a7d5a",
+ "shasum": ""
+ },
+ "require": {
+ "opis/string": "^2.0",
+ "php": "^7.4 || ^8.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^9"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Opis\\Uri\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "Apache-2.0"
+ ],
+ "authors": [
+ {
+ "name": "Marius Sarca",
+ "email": "marius.sarca@gmail.com"
+ },
+ {
+ "name": "Sorin Sarca",
+ "email": "sarca_sorin@hotmail.com"
+ }
+ ],
+ "description": "Build, parse and validate URIs and URI-templates",
+ "homepage": "https://opis.io",
+ "keywords": [
+ "URI Template",
+ "parse url",
+ "punycode",
+ "uri",
+ "uri components",
+ "url",
+ "validate uri"
+ ],
+ "support": {
+ "issues": "https://github.com/opis/uri/issues",
+ "source": "https://github.com/opis/uri/tree/1.1.0"
+ },
+ "time": "2021-05-22T15:57:08+00:00"
+ },
+ {
+ "name": "pestphp/pest",
+ "version": "v4.7.8",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/pestphp/pest.git",
+ "reference": "5b2293f67adcf1b2320b33f521b94a692d18f360"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/pestphp/pest/zipball/5b2293f67adcf1b2320b33f521b94a692d18f360",
+ "reference": "5b2293f67adcf1b2320b33f521b94a692d18f360",
+ "shasum": ""
+ },
+ "require": {
+ "brianium/paratest": "^7.20.0",
+ "composer/xdebug-handler": "^3.0.5",
+ "nunomaduro/collision": "^8.9.5",
+ "nunomaduro/termwind": "^2.4.0",
+ "pestphp/pest-plugin": "^4.0.0",
+ "pestphp/pest-plugin-arch": "^4.0.2",
+ "pestphp/pest-plugin-mutate": "^4.0.1",
+ "pestphp/pest-plugin-profanity": "^4.2.1",
+ "php": "^8.3.0",
+ "phpunit/phpunit": "^12.5.33",
+ "symfony/process": "^7.4.13|^8.1.0"
+ },
+ "conflict": {
+ "filp/whoops": "<2.18.3",
+ "phpunit/phpunit": ">12.5.33",
+ "sebastian/exporter": "<7.0.0",
+ "webmozart/assert": "<1.11.0"
+ },
+ "require-dev": {
+ "mrpunyapal/peststan": "^0.2.12",
+ "pestphp/pest-dev-tools": "^4.1.0",
+ "pestphp/pest-plugin-browser": "^4.3.1",
+ "pestphp/pest-plugin-type-coverage": "^4.0.4",
+ "psy/psysh": "^0.12.24"
+ },
+ "bin": [
+ "bin/pest"
+ ],
+ "type": "library",
+ "extra": {
+ "pest": {
+ "plugins": [
+ "Pest\\Mutate\\Plugins\\Mutate",
+ "Pest\\Plugins\\Configuration",
+ "Pest\\Plugins\\Bail",
+ "Pest\\Plugins\\Cache",
+ "Pest\\Plugins\\Coverage",
+ "Pest\\Plugins\\Init",
+ "Pest\\Plugins\\Environment",
+ "Pest\\Plugins\\Help",
+ "Pest\\Plugins\\Memory",
+ "Pest\\Plugins\\Only",
+ "Pest\\Plugins\\Printer",
+ "Pest\\Plugins\\ProcessIsolation",
+ "Pest\\Plugins\\Profile",
+ "Pest\\Plugins\\Retry",
+ "Pest\\Plugins\\Snapshot",
+ "Pest\\Plugins\\Verbose",
+ "Pest\\Plugins\\Version",
+ "Pest\\Plugins\\Shard",
+ "Pest\\Plugins\\Parallel"
+ ]
+ },
+ "phpstan": {
+ "includes": [
+ "extension.neon"
+ ]
+ }
+ },
+ "autoload": {
+ "files": [
+ "src/Functions.php",
+ "src/Pest.php"
+ ],
+ "psr-4": {
+ "Pest\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Nuno Maduro",
+ "email": "enunomaduro@gmail.com"
+ }
+ ],
+ "description": "The elegant PHP Testing Framework.",
+ "keywords": [
+ "framework",
+ "pest",
+ "php",
+ "test",
+ "testing",
+ "unit"
+ ],
+ "support": {
+ "issues": "https://github.com/pestphp/pest/issues",
+ "source": "https://github.com/pestphp/pest/tree/v4.7.8"
+ },
+ "funding": [
+ {
+ "url": "https://www.paypal.com/paypalme/enunomaduro",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/nunomaduro",
+ "type": "github"
+ }
+ ],
+ "time": "2026-08-03T20:49:44+00:00"
+ },
+ {
+ "name": "pestphp/pest-plugin",
+ "version": "v4.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/pestphp/pest-plugin.git",
+ "reference": "9d4b93d7f73d3f9c3189bb22c220fef271cdf568"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/pestphp/pest-plugin/zipball/9d4b93d7f73d3f9c3189bb22c220fef271cdf568",
+ "reference": "9d4b93d7f73d3f9c3189bb22c220fef271cdf568",
+ "shasum": ""
+ },
+ "require": {
+ "composer-plugin-api": "^2.0.0",
+ "composer-runtime-api": "^2.2.2",
+ "php": "^8.3"
+ },
+ "conflict": {
+ "pestphp/pest": "<4.0.0"
+ },
+ "require-dev": {
+ "composer/composer": "^2.8.10",
+ "pestphp/pest": "^4.0.0",
+ "pestphp/pest-dev-tools": "^4.0.0"
+ },
+ "type": "composer-plugin",
+ "extra": {
+ "class": "Pest\\Plugin\\Manager"
+ },
+ "autoload": {
+ "psr-4": {
+ "Pest\\Plugin\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "description": "The Pest plugin manager",
+ "keywords": [
+ "framework",
+ "manager",
+ "pest",
+ "php",
+ "plugin",
+ "test",
+ "testing",
+ "unit"
+ ],
+ "support": {
+ "source": "https://github.com/pestphp/pest-plugin/tree/v4.0.0"
+ },
+ "funding": [
+ {
+ "url": "https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=66BYDWAT92N6L",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/nunomaduro",
+ "type": "github"
+ },
+ {
+ "url": "https://www.patreon.com/nunomaduro",
+ "type": "patreon"
+ }
+ ],
+ "time": "2025-08-20T12:35:58+00:00"
+ },
+ {
+ "name": "pestphp/pest-plugin-arch",
+ "version": "v4.0.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/pestphp/pest-plugin-arch.git",
+ "reference": "3fb0d02a91b9da504b139dc7ab2a31efb7c3215c"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/pestphp/pest-plugin-arch/zipball/3fb0d02a91b9da504b139dc7ab2a31efb7c3215c",
+ "reference": "3fb0d02a91b9da504b139dc7ab2a31efb7c3215c",
+ "shasum": ""
+ },
+ "require": {
+ "pestphp/pest-plugin": "^4.0.0",
+ "php": "^8.3",
+ "ta-tikoma/phpunit-architecture-test": "^0.8.7"
+ },
+ "require-dev": {
+ "pestphp/pest": "^4.4.6",
+ "pestphp/pest-dev-tools": "^4.1.0"
+ },
+ "type": "library",
+ "extra": {
+ "pest": {
+ "plugins": [
+ "Pest\\Arch\\Plugin"
+ ]
+ }
+ },
+ "autoload": {
+ "files": [
+ "src/Autoload.php"
+ ],
+ "psr-4": {
+ "Pest\\Arch\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "description": "The Arch plugin for Pest PHP.",
+ "keywords": [
+ "arch",
+ "architecture",
+ "framework",
+ "pest",
+ "php",
+ "plugin",
+ "test",
+ "testing",
+ "unit"
+ ],
+ "support": {
+ "source": "https://github.com/pestphp/pest-plugin-arch/tree/v4.0.2"
+ },
+ "funding": [
+ {
+ "url": "https://www.paypal.com/paypalme/enunomaduro",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/nunomaduro",
+ "type": "github"
+ }
+ ],
+ "time": "2026-04-10T17:20:19+00:00"
+ },
+ {
+ "name": "pestphp/pest-plugin-faker",
+ "version": "v4.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/pestphp/pest-plugin-faker.git",
+ "reference": "afb07eeca115cc19a2f5e20a4ec113ee6e26d4ec"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/pestphp/pest-plugin-faker/zipball/afb07eeca115cc19a2f5e20a4ec113ee6e26d4ec",
+ "reference": "afb07eeca115cc19a2f5e20a4ec113ee6e26d4ec",
+ "shasum": ""
+ },
+ "require": {
+ "fakerphp/faker": "^1.24.1",
+ "pestphp/pest": "^4.0.0",
+ "php": "^8.3.0"
+ },
+ "require-dev": {
+ "pestphp/pest-dev-tools": "^4.0.0"
+ },
+ "type": "library",
+ "autoload": {
+ "files": [
+ "src/Faker.php"
+ ],
+ "psr-4": {
+ "Pest\\Faker\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "description": "The Pest Faker Plugin",
+ "keywords": [
+ "faker",
+ "framework",
+ "pest",
+ "php",
+ "plugin",
+ "test",
+ "testing",
+ "unit"
+ ],
+ "support": {
+ "source": "https://github.com/pestphp/pest-plugin-faker/tree/v4.0.0"
+ },
+ "funding": [
+ {
+ "url": "https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=66BYDWAT92N6L",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/nunomaduro",
+ "type": "github"
+ },
+ {
+ "url": "https://www.patreon.com/nunomaduro",
+ "type": "patreon"
+ }
+ ],
+ "time": "2025-08-20T10:22:28+00:00"
+ },
+ {
+ "name": "pestphp/pest-plugin-laravel",
+ "version": "v4.1.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/pestphp/pest-plugin-laravel.git",
+ "reference": "3057a36669ff11416cc0dc2b521b3aec58c488d0"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/pestphp/pest-plugin-laravel/zipball/3057a36669ff11416cc0dc2b521b3aec58c488d0",
+ "reference": "3057a36669ff11416cc0dc2b521b3aec58c488d0",
+ "shasum": ""
+ },
+ "require": {
+ "laravel/framework": "^11.45.2|^12.52.0|^13.0",
+ "pestphp/pest": "^4.4.1",
+ "php": "^8.3.0"
+ },
+ "require-dev": {
+ "laravel/dusk": "^8.3.6",
+ "orchestra/testbench": "^9.13.0|^10.9.0|^11.0",
+ "pestphp/pest-dev-tools": "^4.1.0"
+ },
+ "type": "library",
+ "extra": {
+ "pest": {
+ "plugins": [
+ "Pest\\Laravel\\Plugin"
+ ]
+ },
+ "laravel": {
+ "providers": [
+ "Pest\\Laravel\\PestServiceProvider"
+ ]
+ }
+ },
+ "autoload": {
+ "files": [
+ "src/Autoload.php"
+ ],
+ "psr-4": {
+ "Pest\\Laravel\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "description": "The Pest Laravel Plugin",
+ "keywords": [
+ "framework",
+ "laravel",
+ "pest",
+ "php",
+ "test",
+ "testing",
+ "unit"
+ ],
+ "support": {
+ "source": "https://github.com/pestphp/pest-plugin-laravel/tree/v4.1.0"
+ },
+ "funding": [
+ {
+ "url": "https://www.paypal.com/paypalme/enunomaduro",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/nunomaduro",
+ "type": "github"
+ }
+ ],
+ "time": "2026-02-21T00:29:45+00:00"
+ },
+ {
+ "name": "pestphp/pest-plugin-mutate",
+ "version": "v4.0.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/pestphp/pest-plugin-mutate.git",
+ "reference": "d9b32b60b2385e1688a68cc227594738ec26d96c"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/pestphp/pest-plugin-mutate/zipball/d9b32b60b2385e1688a68cc227594738ec26d96c",
+ "reference": "d9b32b60b2385e1688a68cc227594738ec26d96c",
+ "shasum": ""
+ },
+ "require": {
+ "nikic/php-parser": "^5.6.1",
+ "pestphp/pest-plugin": "^4.0.0",
+ "php": "^8.3",
+ "psr/simple-cache": "^3.0.0"
+ },
+ "require-dev": {
+ "pestphp/pest": "^4.0.0",
+ "pestphp/pest-dev-tools": "^4.0.0",
+ "pestphp/pest-plugin-type-coverage": "^4.0.0"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Pest\\Mutate\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Nuno Maduro",
+ "email": "enunomaduro@gmail.com"
+ },
+ {
+ "name": "Sandro Gehri",
+ "email": "sandrogehri@gmail.com"
+ }
+ ],
+ "description": "Mutates your code to find untested cases",
+ "keywords": [
+ "framework",
+ "mutate",
+ "mutation",
+ "pest",
+ "php",
+ "plugin",
+ "test",
+ "testing",
+ "unit"
+ ],
+ "support": {
+ "source": "https://github.com/pestphp/pest-plugin-mutate/tree/v4.0.1"
+ },
+ "funding": [
+ {
+ "url": "https://www.paypal.com/paypalme/enunomaduro",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/gehrisandro",
+ "type": "github"
+ },
+ {
+ "url": "https://github.com/nunomaduro",
+ "type": "github"
+ }
+ ],
+ "time": "2025-08-21T20:19:25+00:00"
+ },
+ {
+ "name": "pestphp/pest-plugin-profanity",
+ "version": "v4.2.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/pestphp/pest-plugin-profanity.git",
+ "reference": "343cfa6f3564b7e35df0ebb77b7fa97039f72b27"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/pestphp/pest-plugin-profanity/zipball/343cfa6f3564b7e35df0ebb77b7fa97039f72b27",
+ "reference": "343cfa6f3564b7e35df0ebb77b7fa97039f72b27",
+ "shasum": ""
+ },
+ "require": {
+ "pestphp/pest-plugin": "^4.0.0",
+ "php": "^8.3"
+ },
+ "require-dev": {
+ "faissaloux/pest-plugin-inside": "^1.9",
+ "pestphp/pest": "^4.0.0",
+ "pestphp/pest-dev-tools": "^4.0.0"
+ },
+ "type": "library",
+ "extra": {
+ "pest": {
+ "plugins": [
+ "Pest\\Profanity\\Plugin"
+ ]
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Pest\\Profanity\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "description": "The Pest Profanity Plugin",
+ "keywords": [
+ "framework",
+ "pest",
+ "php",
+ "plugin",
+ "profanity",
+ "test",
+ "testing",
+ "unit"
+ ],
+ "support": {
+ "source": "https://github.com/pestphp/pest-plugin-profanity/tree/v4.2.1"
+ },
+ "time": "2025-12-08T00:13:17+00:00"
+ },
+ {
+ "name": "pestphp/pest-plugin-type-coverage",
+ "version": "v4.0.4",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/pestphp/pest-plugin-type-coverage.git",
+ "reference": "f485d40ec4e2081f9d3456c00f2c008f145d7896"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/pestphp/pest-plugin-type-coverage/zipball/f485d40ec4e2081f9d3456c00f2c008f145d7896",
+ "reference": "f485d40ec4e2081f9d3456c00f2c008f145d7896",
+ "shasum": ""
+ },
+ "require": {
+ "nunomaduro/pokio": "^1.0.0",
+ "pestphp/pest-plugin": "^4.0.0",
+ "php": "^8.3",
+ "phpstan/phpstan": "^1.12.24|^2.1.46",
+ "tomasvotruba/type-coverage": "^1.0.0|^2.1.0"
+ },
+ "require-dev": {
+ "pestphp/pest": "^4.4.5",
+ "pestphp/pest-dev-tools": "^4.1.0"
+ },
+ "type": "library",
+ "extra": {
+ "pest": {
+ "plugins": [
+ "Pest\\TypeCoverage\\Plugin"
+ ]
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Pest\\TypeCoverage\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "description": "The Type Coverage plugin for Pest PHP.",
+ "keywords": [
+ "coverage",
+ "framework",
+ "pest",
+ "php",
+ "plugin",
+ "test",
+ "testing",
+ "type-coverage",
+ "unit"
+ ],
+ "support": {
+ "source": "https://github.com/pestphp/pest-plugin-type-coverage/tree/v4.0.4"
+ },
+ "funding": [
+ {
+ "url": "https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=66BYDWAT92N6L",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/nunomaduro",
+ "type": "github"
+ }
+ ],
+ "time": "2026-04-06T14:00:30+00:00"
+ },
+ {
+ "name": "phar-io/manifest",
+ "version": "2.0.4",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/phar-io/manifest.git",
+ "reference": "54750ef60c58e43759730615a392c31c80e23176"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/phar-io/manifest/zipball/54750ef60c58e43759730615a392c31c80e23176",
+ "reference": "54750ef60c58e43759730615a392c31c80e23176",
+ "shasum": ""
+ },
+ "require": {
+ "ext-dom": "*",
+ "ext-libxml": "*",
+ "ext-phar": "*",
+ "ext-xmlwriter": "*",
+ "phar-io/version": "^3.0.1",
+ "php": "^7.2 || ^8.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.0.x-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Arne Blankerts",
+ "email": "arne@blankerts.de",
+ "role": "Developer"
+ },
+ {
+ "name": "Sebastian Heuer",
+ "email": "sebastian@phpeople.de",
+ "role": "Developer"
+ },
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de",
+ "role": "Developer"
+ }
+ ],
+ "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)",
+ "support": {
+ "issues": "https://github.com/phar-io/manifest/issues",
+ "source": "https://github.com/phar-io/manifest/tree/2.0.4"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/theseer",
+ "type": "github"
+ }
+ ],
+ "time": "2024-03-03T12:33:53+00:00"
+ },
+ {
+ "name": "phar-io/version",
+ "version": "3.2.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/phar-io/version.git",
+ "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/phar-io/version/zipball/4f7fd7836c6f332bb2933569e566a0d6c4cbed74",
+ "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^7.2 || ^8.0"
+ },
+ "type": "library",
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Arne Blankerts",
+ "email": "arne@blankerts.de",
+ "role": "Developer"
+ },
+ {
+ "name": "Sebastian Heuer",
+ "email": "sebastian@phpeople.de",
+ "role": "Developer"
+ },
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de",
+ "role": "Developer"
+ }
+ ],
+ "description": "Library for handling version information and constraints",
+ "support": {
+ "issues": "https://github.com/phar-io/version/issues",
+ "source": "https://github.com/phar-io/version/tree/3.2.1"
+ },
+ "time": "2022-02-21T01:04:05+00:00"
+ },
+ {
+ "name": "php-parallel-lint/php-parallel-lint",
+ "version": "v1.4.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/php-parallel-lint/PHP-Parallel-Lint.git",
+ "reference": "6db563514f27e19595a19f45a4bf757b6401194e"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/php-parallel-lint/PHP-Parallel-Lint/zipball/6db563514f27e19595a19f45a4bf757b6401194e",
+ "reference": "6db563514f27e19595a19f45a4bf757b6401194e",
+ "shasum": ""
+ },
+ "require": {
+ "ext-json": "*",
+ "php": ">=5.3.0"
+ },
+ "replace": {
+ "grogy/php-parallel-lint": "*",
+ "jakub-onderka/php-parallel-lint": "*"
+ },
+ "require-dev": {
+ "nette/tester": "^1.3 || ^2.0",
+ "php-parallel-lint/php-console-highlighter": "0.* || ^1.0",
+ "squizlabs/php_codesniffer": "^3.6"
+ },
+ "suggest": {
+ "php-parallel-lint/php-console-highlighter": "Highlight syntax in code snippet"
+ },
+ "bin": [
+ "parallel-lint"
+ ],
+ "type": "library",
+ "autoload": {
+ "classmap": [
+ "./src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-2-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Jakub Onderka",
+ "email": "ahoj@jakubonderka.cz"
+ }
+ ],
+ "description": "This tool checks the syntax of PHP files about 20x faster than serial check.",
+ "homepage": "https://github.com/php-parallel-lint/PHP-Parallel-Lint",
+ "keywords": [
+ "lint",
+ "static analysis"
+ ],
+ "support": {
+ "issues": "https://github.com/php-parallel-lint/PHP-Parallel-Lint/issues",
+ "source": "https://github.com/php-parallel-lint/PHP-Parallel-Lint/tree/v1.4.0"
+ },
+ "time": "2024-03-27T12:14:49+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": "6.0.3",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git",
+ "reference": "7bae67520aa9f5ecc506d646810bd40d9da54582"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/7bae67520aa9f5ecc506d646810bd40d9da54582",
+ "reference": "7bae67520aa9f5ecc506d646810bd40d9da54582",
+ "shasum": ""
+ },
+ "require": {
+ "doctrine/deprecations": "^1.1",
+ "ext-filter": "*",
+ "php": "^7.4 || ^8.0",
+ "phpdocumentor/reflection-common": "^2.2",
+ "phpdocumentor/type-resolver": "^2.0",
+ "phpstan/phpdoc-parser": "^2.0",
+ "webmozart/assert": "^1.9.1 || ^2"
+ },
+ "require-dev": {
+ "mockery/mockery": "~1.3.5 || ~1.6.0",
+ "phpstan/extension-installer": "^1.1",
+ "phpstan/phpstan": "^1.8",
+ "phpstan/phpstan-mockery": "^1.1",
+ "phpstan/phpstan-webmozart-assert": "^1.2",
+ "phpunit/phpunit": "^9.5",
+ "psalm/phar": "^5.26",
+ "shipmonk/dead-code-detector": "^0.5.1"
+ },
+ "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/6.0.3"
+ },
+ "time": "2026-03-18T20:49:53+00:00"
+ },
+ {
+ "name": "phpdocumentor/type-resolver",
+ "version": "2.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/phpDocumentor/TypeResolver.git",
+ "reference": "327a05bbee54120d4786a0dc67aad30226ad4cf9"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/327a05bbee54120d4786a0dc67aad30226ad4cf9",
+ "reference": "327a05bbee54120d4786a0dc67aad30226ad4cf9",
+ "shasum": ""
+ },
+ "require": {
+ "doctrine/deprecations": "^1.0",
+ "php": "^7.4 || ^8.0",
+ "phpdocumentor/reflection-common": "^2.0",
+ "phpstan/phpdoc-parser": "^2.0"
+ },
+ "require-dev": {
+ "ext-tokenizer": "*",
+ "phpbench/phpbench": "^1.2",
+ "phpstan/extension-installer": "^1.4",
+ "phpstan/phpstan": "^2.1",
+ "phpstan/phpstan-phpunit": "^2.0",
+ "phpunit/phpunit": "^9.5",
+ "psalm/phar": "^4"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-1.x": "1.x-dev",
+ "dev-2.x": "2.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/2.0.0"
+ },
+ "time": "2026-01-06T21:53:42+00:00"
+ },
+ {
+ "name": "phpstan/phpdoc-parser",
+ "version": "2.3.3",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/phpstan/phpdoc-parser.git",
+ "reference": "fb19eedd2bb67ff8cf7a5502ad329e701d6398a3"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/fb19eedd2bb67ff8cf7a5502ad329e701d6398a3",
+ "reference": "fb19eedd2bb67ff8cf7a5502ad329e701d6398a3",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^7.4 || ^8.0"
+ },
+ "require-dev": {
+ "doctrine/annotations": "^2.0",
+ "nikic/php-parser": "^5.3.0",
+ "php-parallel-lint/php-parallel-lint": "^1.2",
+ "phpstan/extension-installer": "^1.0",
+ "phpstan/phpstan": "^2.0",
+ "phpstan/phpstan-phpunit": "^2.0",
+ "phpstan/phpstan-strict-rules": "^2.0",
+ "phpunit/phpunit": "^9.6",
+ "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/2.3.3"
+ },
+ "time": "2026-07-08T07:01:06+00:00"
+ },
+ {
+ "name": "phpunit/php-code-coverage",
+ "version": "12.5.7",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/php-code-coverage.git",
+ "reference": "186dab580576598076de6818596d12b61801880e"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/186dab580576598076de6818596d12b61801880e",
+ "reference": "186dab580576598076de6818596d12b61801880e",
+ "shasum": ""
+ },
+ "require": {
+ "ext-dom": "*",
+ "ext-libxml": "*",
+ "ext-xmlwriter": "*",
+ "nikic/php-parser": "^5.7.0",
+ "php": ">=8.3",
+ "phpunit/php-text-template": "^5.0",
+ "sebastian/complexity": "^5.0",
+ "sebastian/environment": "^8.1.2",
+ "sebastian/lines-of-code": "^4.0.1",
+ "sebastian/version": "^6.0",
+ "theseer/tokenizer": "^2.0.1"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^12.5.28"
+ },
+ "suggest": {
+ "ext-pcov": "PHP extension that provides line coverage",
+ "ext-xdebug": "PHP extension that provides line coverage as well as branch and path coverage"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "12.5.x-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de",
+ "role": "lead"
+ }
+ ],
+ "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.",
+ "homepage": "https://github.com/sebastianbergmann/php-code-coverage",
+ "keywords": [
+ "coverage",
+ "testing",
+ "xunit"
+ ],
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues",
+ "security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy",
+ "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/12.5.7"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ },
+ {
+ "url": "https://liberapay.com/sebastianbergmann",
+ "type": "liberapay"
+ },
+ {
+ "url": "https://thanks.dev/u/gh/sebastianbergmann",
+ "type": "thanks_dev"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/phpunit/php-code-coverage",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2026-06-01T13:24:19+00:00"
+ },
+ {
+ "name": "phpunit/php-file-iterator",
+ "version": "6.0.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/php-file-iterator.git",
+ "reference": "3d1cd096ef6bea4bf2762ba586e35dbd317cbfd5"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/3d1cd096ef6bea4bf2762ba586e35dbd317cbfd5",
+ "reference": "3d1cd096ef6bea4bf2762ba586e35dbd317cbfd5",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.3"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^12.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "6.0-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de",
+ "role": "lead"
+ }
+ ],
+ "description": "FilterIterator implementation that filters files based on a list of suffixes.",
+ "homepage": "https://github.com/sebastianbergmann/php-file-iterator/",
+ "keywords": [
+ "filesystem",
+ "iterator"
+ ],
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues",
+ "security": "https://github.com/sebastianbergmann/php-file-iterator/security/policy",
+ "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/6.0.1"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ },
+ {
+ "url": "https://liberapay.com/sebastianbergmann",
+ "type": "liberapay"
+ },
+ {
+ "url": "https://thanks.dev/u/gh/sebastianbergmann",
+ "type": "thanks_dev"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/phpunit/php-file-iterator",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2026-02-02T14:04:18+00:00"
+ },
+ {
+ "name": "phpunit/php-invoker",
+ "version": "6.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/php-invoker.git",
+ "reference": "12b54e689b07a25a9b41e57736dfab6ec9ae5406"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/12b54e689b07a25a9b41e57736dfab6ec9ae5406",
+ "reference": "12b54e689b07a25a9b41e57736dfab6ec9ae5406",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.3"
+ },
+ "require-dev": {
+ "ext-pcntl": "*",
+ "phpunit/phpunit": "^12.0"
+ },
+ "suggest": {
+ "ext-pcntl": "*"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "6.0-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de",
+ "role": "lead"
+ }
+ ],
+ "description": "Invoke callables with a timeout",
+ "homepage": "https://github.com/sebastianbergmann/php-invoker/",
+ "keywords": [
+ "process"
+ ],
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/php-invoker/issues",
+ "security": "https://github.com/sebastianbergmann/php-invoker/security/policy",
+ "source": "https://github.com/sebastianbergmann/php-invoker/tree/6.0.0"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ }
+ ],
+ "time": "2025-02-07T04:58:58+00:00"
+ },
+ {
+ "name": "phpunit/php-text-template",
+ "version": "5.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/php-text-template.git",
+ "reference": "e1367a453f0eda562eedb4f659e13aa900d66c53"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/e1367a453f0eda562eedb4f659e13aa900d66c53",
+ "reference": "e1367a453f0eda562eedb4f659e13aa900d66c53",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.3"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^12.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "5.0-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de",
+ "role": "lead"
+ }
+ ],
+ "description": "Simple template engine.",
+ "homepage": "https://github.com/sebastianbergmann/php-text-template/",
+ "keywords": [
+ "template"
+ ],
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/php-text-template/issues",
+ "security": "https://github.com/sebastianbergmann/php-text-template/security/policy",
+ "source": "https://github.com/sebastianbergmann/php-text-template/tree/5.0.0"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ }
+ ],
+ "time": "2025-02-07T04:59:16+00:00"
+ },
+ {
+ "name": "phpunit/php-timer",
+ "version": "8.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/php-timer.git",
+ "reference": "f258ce36aa457f3aa3339f9ed4c81fc66dc8c2cc"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/f258ce36aa457f3aa3339f9ed4c81fc66dc8c2cc",
+ "reference": "f258ce36aa457f3aa3339f9ed4c81fc66dc8c2cc",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.3"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^12.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "8.0-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de",
+ "role": "lead"
+ }
+ ],
+ "description": "Utility class for timing",
+ "homepage": "https://github.com/sebastianbergmann/php-timer/",
+ "keywords": [
+ "timer"
+ ],
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/php-timer/issues",
+ "security": "https://github.com/sebastianbergmann/php-timer/security/policy",
+ "source": "https://github.com/sebastianbergmann/php-timer/tree/8.0.0"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ }
+ ],
+ "time": "2025-02-07T04:59:38+00:00"
+ },
+ {
+ "name": "phpunit/phpunit",
+ "version": "12.5.33",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/phpunit.git",
+ "reference": "b98e028a26c5c5ba7e4a54be96ccf35f2914d184"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/b98e028a26c5c5ba7e4a54be96ccf35f2914d184",
+ "reference": "b98e028a26c5c5ba7e4a54be96ccf35f2914d184",
+ "shasum": ""
+ },
+ "require": {
+ "ext-dom": "*",
+ "ext-filter": "*",
+ "ext-json": "*",
+ "ext-libxml": "*",
+ "ext-mbstring": "*",
+ "ext-xmlwriter": "*",
+ "myclabs/deep-copy": "^1.13.4",
+ "phar-io/manifest": "^2.0.4",
+ "phar-io/version": "^3.2.1",
+ "php": ">=8.3",
+ "phpunit/php-code-coverage": "^12.5.7",
+ "phpunit/php-file-iterator": "^6.0.1",
+ "phpunit/php-invoker": "^6.0.0",
+ "phpunit/php-text-template": "^5.0.0",
+ "phpunit/php-timer": "^8.0.0",
+ "sebastian/cli-parser": "^4.2.1",
+ "sebastian/comparator": "^7.1.8",
+ "sebastian/diff": "^7.0.0",
+ "sebastian/environment": "^8.1.2",
+ "sebastian/exporter": "^7.0.3",
+ "sebastian/global-state": "^8.0.3",
+ "sebastian/object-enumerator": "^7.0.0",
+ "sebastian/recursion-context": "^7.0.1",
+ "sebastian/type": "^6.0.4",
+ "sebastian/version": "^6.0.0",
+ "staabm/side-effects-detector": "^1.0.5"
+ },
+ "bin": [
+ "phpunit"
+ ],
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "12.5-dev"
+ }
+ },
+ "autoload": {
+ "files": [
+ "src/Framework/Assert/Functions.php"
+ ],
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de",
+ "role": "lead"
+ }
+ ],
+ "description": "The PHP Unit Testing framework.",
+ "homepage": "https://phpunit.de/",
+ "keywords": [
+ "phpunit",
+ "testing",
+ "xunit"
+ ],
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/phpunit/issues",
+ "security": "https://github.com/sebastianbergmann/phpunit/security/policy",
+ "source": "https://github.com/sebastianbergmann/phpunit/tree/12.5.33"
+ },
+ "funding": [
+ {
+ "url": "https://phpunit.de/sponsoring.html",
+ "type": "other"
+ }
+ ],
+ "time": "2026-07-28T13:58:09+00:00"
+ },
+ {
+ "name": "react/event-loop",
+ "version": "v1.6.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/reactphp/event-loop.git",
+ "reference": "ba276bda6083df7e0050fd9b33f66ad7a4ac747a"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/reactphp/event-loop/zipball/ba276bda6083df7e0050fd9b33f66ad7a4ac747a",
+ "reference": "ba276bda6083df7e0050fd9b33f66ad7a4ac747a",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^9.6 || ^5.7 || ^4.8.36"
+ },
+ "suggest": {
+ "ext-pcntl": "For signal handling support when using the StreamSelectLoop"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "React\\EventLoop\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Christian Lück",
+ "email": "christian@clue.engineering",
+ "homepage": "https://clue.engineering/"
+ },
+ {
+ "name": "Cees-Jan Kiewiet",
+ "email": "reactphp@ceesjankiewiet.nl",
+ "homepage": "https://wyrihaximus.net/"
+ },
+ {
+ "name": "Jan Sorgalla",
+ "email": "jsorgalla@gmail.com",
+ "homepage": "https://sorgalla.com/"
+ },
+ {
+ "name": "Chris Boden",
+ "email": "cboden@gmail.com",
+ "homepage": "https://cboden.dev/"
+ }
+ ],
+ "description": "ReactPHP's core reactor event loop that libraries can use for evented I/O.",
+ "keywords": [
+ "asynchronous",
+ "event-loop"
+ ],
+ "support": {
+ "issues": "https://github.com/reactphp/event-loop/issues",
+ "source": "https://github.com/reactphp/event-loop/tree/v1.6.0"
+ },
+ "funding": [
+ {
+ "url": "https://opencollective.com/reactphp",
+ "type": "open_collective"
+ }
+ ],
+ "time": "2025-11-17T20:46:25+00:00"
+ },
+ {
+ "name": "sebastian/cli-parser",
+ "version": "4.2.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/cli-parser.git",
+ "reference": "7d05781b13f7dec9043a629a21d086ed74582a15"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/7d05781b13f7dec9043a629a21d086ed74582a15",
+ "reference": "7d05781b13f7dec9043a629a21d086ed74582a15",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.3"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^12.5.25"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "4.2-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de",
+ "role": "lead"
+ }
+ ],
+ "description": "Library for parsing CLI options",
+ "homepage": "https://github.com/sebastianbergmann/cli-parser",
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/cli-parser/issues",
+ "security": "https://github.com/sebastianbergmann/cli-parser/security/policy",
+ "source": "https://github.com/sebastianbergmann/cli-parser/tree/4.2.1"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ },
+ {
+ "url": "https://liberapay.com/sebastianbergmann",
+ "type": "liberapay"
+ },
+ {
+ "url": "https://thanks.dev/u/gh/sebastianbergmann",
+ "type": "thanks_dev"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/sebastian/cli-parser",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2026-05-17T05:29:34+00:00"
+ },
+ {
+ "name": "sebastian/comparator",
+ "version": "7.1.8",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/comparator.git",
+ "reference": "7c65c1e79836812819705b473a90c12399542485"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/7c65c1e79836812819705b473a90c12399542485",
+ "reference": "7c65c1e79836812819705b473a90c12399542485",
+ "shasum": ""
+ },
+ "require": {
+ "ext-dom": "*",
+ "ext-mbstring": "*",
+ "php": ">=8.3",
+ "sebastian/diff": "^7.0",
+ "sebastian/exporter": "^7.0.3"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^12.5.25"
+ },
+ "suggest": {
+ "ext-bcmath": "For comparing BcMath\\Number objects"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "7.1-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de"
+ },
+ {
+ "name": "Jeff Welch",
+ "email": "whatthejeff@gmail.com"
+ },
+ {
+ "name": "Volker Dusch",
+ "email": "github@wallbash.com"
+ },
+ {
+ "name": "Bernhard Schussek",
+ "email": "bschussek@2bepublished.at"
+ }
+ ],
+ "description": "Provides the functionality to compare PHP values for equality",
+ "homepage": "https://github.com/sebastianbergmann/comparator",
+ "keywords": [
+ "comparator",
+ "compare",
+ "equality"
+ ],
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/comparator/issues",
+ "security": "https://github.com/sebastianbergmann/comparator/security/policy",
+ "source": "https://github.com/sebastianbergmann/comparator/tree/7.1.8"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ },
+ {
+ "url": "https://liberapay.com/sebastianbergmann",
+ "type": "liberapay"
+ },
+ {
+ "url": "https://thanks.dev/u/gh/sebastianbergmann",
+ "type": "thanks_dev"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/sebastian/comparator",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2026-05-21T04:45:25+00:00"
+ },
+ {
+ "name": "sebastian/complexity",
+ "version": "5.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/complexity.git",
+ "reference": "bad4316aba5303d0221f43f8cee37eb58d384bbb"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/bad4316aba5303d0221f43f8cee37eb58d384bbb",
+ "reference": "bad4316aba5303d0221f43f8cee37eb58d384bbb",
+ "shasum": ""
+ },
+ "require": {
+ "nikic/php-parser": "^5.0",
+ "php": ">=8.3"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^12.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "5.0-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de",
+ "role": "lead"
+ }
+ ],
+ "description": "Library for calculating the complexity of PHP code units",
+ "homepage": "https://github.com/sebastianbergmann/complexity",
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/complexity/issues",
+ "security": "https://github.com/sebastianbergmann/complexity/security/policy",
+ "source": "https://github.com/sebastianbergmann/complexity/tree/5.0.0"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ }
+ ],
+ "time": "2025-02-07T04:55:25+00:00"
+ },
+ {
+ "name": "sebastian/diff",
+ "version": "7.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/diff.git",
+ "reference": "7ab1ea946c012266ca32390913653d844ecd085f"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/7ab1ea946c012266ca32390913653d844ecd085f",
+ "reference": "7ab1ea946c012266ca32390913653d844ecd085f",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.3"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^12.0",
+ "symfony/process": "^7.2"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "7.0-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de"
+ },
+ {
+ "name": "Kore Nordmann",
+ "email": "mail@kore-nordmann.de"
+ }
+ ],
+ "description": "Diff implementation",
+ "homepage": "https://github.com/sebastianbergmann/diff",
+ "keywords": [
+ "diff",
+ "udiff",
+ "unidiff",
+ "unified diff"
+ ],
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/diff/issues",
+ "security": "https://github.com/sebastianbergmann/diff/security/policy",
+ "source": "https://github.com/sebastianbergmann/diff/tree/7.0.0"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ }
+ ],
+ "time": "2025-02-07T04:55:46+00:00"
+ },
+ {
+ "name": "sebastian/environment",
+ "version": "8.1.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/environment.git",
+ "reference": "9d32c685773823b1983e256ae4ecd48a10d6e439"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/9d32c685773823b1983e256ae4ecd48a10d6e439",
+ "reference": "9d32c685773823b1983e256ae4ecd48a10d6e439",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.3"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^12.5.26"
+ },
+ "suggest": {
+ "ext-posix": "*"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "8.1-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de"
+ }
+ ],
+ "description": "Provides functionality to handle HHVM/PHP environments",
+ "homepage": "https://github.com/sebastianbergmann/environment",
+ "keywords": [
+ "Xdebug",
+ "environment",
+ "hhvm"
+ ],
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/environment/issues",
+ "security": "https://github.com/sebastianbergmann/environment/security/policy",
+ "source": "https://github.com/sebastianbergmann/environment/tree/8.1.2"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ },
+ {
+ "url": "https://liberapay.com/sebastianbergmann",
+ "type": "liberapay"
+ },
+ {
+ "url": "https://thanks.dev/u/gh/sebastianbergmann",
+ "type": "thanks_dev"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/sebastian/environment",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2026-05-25T13:40:20+00:00"
+ },
+ {
+ "name": "sebastian/exporter",
+ "version": "7.0.3",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/exporter.git",
+ "reference": "c5e21b5de653ce0a769fb36f5cdfcb5e7a32cf23"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/c5e21b5de653ce0a769fb36f5cdfcb5e7a32cf23",
+ "reference": "c5e21b5de653ce0a769fb36f5cdfcb5e7a32cf23",
+ "shasum": ""
+ },
+ "require": {
+ "ext-mbstring": "*",
+ "php": ">=8.3",
+ "sebastian/recursion-context": "^7.0.1"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^12.5.25"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "7.0-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de"
+ },
+ {
+ "name": "Jeff Welch",
+ "email": "whatthejeff@gmail.com"
+ },
+ {
+ "name": "Volker Dusch",
+ "email": "github@wallbash.com"
+ },
+ {
+ "name": "Adam Harvey",
+ "email": "aharvey@php.net"
+ },
+ {
+ "name": "Bernhard Schussek",
+ "email": "bschussek@gmail.com"
+ }
+ ],
+ "description": "Provides the functionality to export PHP variables for visualization",
+ "homepage": "https://www.github.com/sebastianbergmann/exporter",
+ "keywords": [
+ "export",
+ "exporter"
+ ],
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/exporter/issues",
+ "security": "https://github.com/sebastianbergmann/exporter/security/policy",
+ "source": "https://github.com/sebastianbergmann/exporter/tree/7.0.3"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ },
+ {
+ "url": "https://liberapay.com/sebastianbergmann",
+ "type": "liberapay"
+ },
+ {
+ "url": "https://thanks.dev/u/gh/sebastianbergmann",
+ "type": "thanks_dev"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/sebastian/exporter",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2026-05-20T04:37:17+00:00"
+ },
+ {
+ "name": "sebastian/global-state",
+ "version": "8.0.3",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/global-state.git",
+ "reference": "b164d3274d6537ab462591c5755f76a8f5b1aae9"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/b164d3274d6537ab462591c5755f76a8f5b1aae9",
+ "reference": "b164d3274d6537ab462591c5755f76a8f5b1aae9",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.3",
+ "sebastian/object-reflector": "^5.0",
+ "sebastian/recursion-context": "^7.0.1"
+ },
+ "require-dev": {
+ "ext-dom": "*",
+ "phpunit/phpunit": "^12.5.28"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "8.0-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de"
+ }
+ ],
+ "description": "Snapshotting of global state",
+ "homepage": "https://www.github.com/sebastianbergmann/global-state",
+ "keywords": [
+ "global state"
+ ],
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/global-state/issues",
+ "security": "https://github.com/sebastianbergmann/global-state/security/policy",
+ "source": "https://github.com/sebastianbergmann/global-state/tree/8.0.3"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ },
+ {
+ "url": "https://liberapay.com/sebastianbergmann",
+ "type": "liberapay"
+ },
+ {
+ "url": "https://thanks.dev/u/gh/sebastianbergmann",
+ "type": "thanks_dev"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/sebastian/global-state",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2026-06-01T15:10:33+00:00"
+ },
+ {
+ "name": "sebastian/lines-of-code",
+ "version": "4.0.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/lines-of-code.git",
+ "reference": "d543b8ef219dcd8da262cbb958639a96bedba10e"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/d543b8ef219dcd8da262cbb958639a96bedba10e",
+ "reference": "d543b8ef219dcd8da262cbb958639a96bedba10e",
+ "shasum": ""
+ },
+ "require": {
+ "nikic/php-parser": "^5.7.0",
+ "php": ">=8.3"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^12.5.25"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "4.0-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de",
+ "role": "lead"
+ }
+ ],
+ "description": "Library for counting the lines of code in PHP source code",
+ "homepage": "https://github.com/sebastianbergmann/lines-of-code",
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/lines-of-code/issues",
+ "security": "https://github.com/sebastianbergmann/lines-of-code/security/policy",
+ "source": "https://github.com/sebastianbergmann/lines-of-code/tree/4.0.1"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ },
+ {
+ "url": "https://liberapay.com/sebastianbergmann",
+ "type": "liberapay"
+ },
+ {
+ "url": "https://thanks.dev/u/gh/sebastianbergmann",
+ "type": "thanks_dev"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/sebastian/lines-of-code",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2026-05-19T16:22:07+00:00"
+ },
+ {
+ "name": "sebastian/object-enumerator",
+ "version": "7.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/object-enumerator.git",
+ "reference": "1effe8e9b8e068e9ae228e542d5d11b5d16db894"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/1effe8e9b8e068e9ae228e542d5d11b5d16db894",
+ "reference": "1effe8e9b8e068e9ae228e542d5d11b5d16db894",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.3",
+ "sebastian/object-reflector": "^5.0",
+ "sebastian/recursion-context": "^7.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^12.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "7.0-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de"
+ }
+ ],
+ "description": "Traverses array structures and object graphs to enumerate all referenced objects",
+ "homepage": "https://github.com/sebastianbergmann/object-enumerator/",
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/object-enumerator/issues",
+ "security": "https://github.com/sebastianbergmann/object-enumerator/security/policy",
+ "source": "https://github.com/sebastianbergmann/object-enumerator/tree/7.0.0"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ }
+ ],
+ "time": "2025-02-07T04:57:48+00:00"
+ },
+ {
+ "name": "sebastian/object-reflector",
+ "version": "5.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/object-reflector.git",
+ "reference": "4bfa827c969c98be1e527abd576533293c634f6a"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/4bfa827c969c98be1e527abd576533293c634f6a",
+ "reference": "4bfa827c969c98be1e527abd576533293c634f6a",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.3"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^12.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "5.0-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de"
+ }
+ ],
+ "description": "Allows reflection of object attributes, including inherited and non-public ones",
+ "homepage": "https://github.com/sebastianbergmann/object-reflector/",
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/object-reflector/issues",
+ "security": "https://github.com/sebastianbergmann/object-reflector/security/policy",
+ "source": "https://github.com/sebastianbergmann/object-reflector/tree/5.0.0"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ }
+ ],
+ "time": "2025-02-07T04:58:17+00:00"
+ },
+ {
+ "name": "sebastian/recursion-context",
+ "version": "7.0.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/recursion-context.git",
+ "reference": "0b01998a7d5b1f122911a66bebcb8d46f0c82d8c"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/0b01998a7d5b1f122911a66bebcb8d46f0c82d8c",
+ "reference": "0b01998a7d5b1f122911a66bebcb8d46f0c82d8c",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.3"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^12.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "7.0-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de"
+ },
+ {
+ "name": "Jeff Welch",
+ "email": "whatthejeff@gmail.com"
+ },
+ {
+ "name": "Adam Harvey",
+ "email": "aharvey@php.net"
+ }
+ ],
+ "description": "Provides functionality to recursively process PHP variables",
+ "homepage": "https://github.com/sebastianbergmann/recursion-context",
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/recursion-context/issues",
+ "security": "https://github.com/sebastianbergmann/recursion-context/security/policy",
+ "source": "https://github.com/sebastianbergmann/recursion-context/tree/7.0.1"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ },
+ {
+ "url": "https://liberapay.com/sebastianbergmann",
+ "type": "liberapay"
+ },
+ {
+ "url": "https://thanks.dev/u/gh/sebastianbergmann",
+ "type": "thanks_dev"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/sebastian/recursion-context",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2025-08-13T04:44:59+00:00"
+ },
+ {
+ "name": "sebastian/type",
+ "version": "6.0.4",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/type.git",
+ "reference": "82ff822c2edc46724be9f7411d3163021f602773"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/82ff822c2edc46724be9f7411d3163021f602773",
+ "reference": "82ff822c2edc46724be9f7411d3163021f602773",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.3"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^12.5.25"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "6.0-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de",
+ "role": "lead"
+ }
+ ],
+ "description": "Collection of value objects that represent the types of the PHP type system",
+ "homepage": "https://github.com/sebastianbergmann/type",
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/type/issues",
+ "security": "https://github.com/sebastianbergmann/type/security/policy",
+ "source": "https://github.com/sebastianbergmann/type/tree/6.0.4"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ },
+ {
+ "url": "https://liberapay.com/sebastianbergmann",
+ "type": "liberapay"
+ },
+ {
+ "url": "https://thanks.dev/u/gh/sebastianbergmann",
+ "type": "thanks_dev"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/sebastian/type",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2026-05-20T06:45:45+00:00"
+ },
+ {
+ "name": "sebastian/version",
+ "version": "6.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/version.git",
+ "reference": "3e6ccf7657d4f0a59200564b08cead899313b53c"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/3e6ccf7657d4f0a59200564b08cead899313b53c",
+ "reference": "3e6ccf7657d4f0a59200564b08cead899313b53c",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.3"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "6.0-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de",
+ "role": "lead"
+ }
+ ],
+ "description": "Library that helps with managing the version number of Git-hosted PHP projects",
+ "homepage": "https://github.com/sebastianbergmann/version",
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/version/issues",
+ "security": "https://github.com/sebastianbergmann/version/security/policy",
+ "source": "https://github.com/sebastianbergmann/version/tree/6.0.0"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ }
+ ],
+ "time": "2025-02-07T05:00:38+00:00"
+ },
+ {
+ "name": "slevomat/coding-standard",
+ "version": "8.31.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/slevomat/coding-standard.git",
+ "reference": "0a40807a48873948bfa7ffce2a4e69ba40cf5e76"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/slevomat/coding-standard/zipball/0a40807a48873948bfa7ffce2a4e69ba40cf5e76",
+ "reference": "0a40807a48873948bfa7ffce2a4e69ba40cf5e76",
+ "shasum": ""
+ },
+ "require": {
+ "dealerdirect/phpcodesniffer-composer-installer": "^0.7 || ^1.2.1",
+ "php": "^7.4 || ^8.0",
+ "phpstan/phpdoc-parser": "^2.3.3",
+ "squizlabs/php_codesniffer": "^4.0.1"
+ },
+ "require-dev": {
+ "phing/phing": "3.0.1|3.1.2",
+ "php-parallel-lint/php-parallel-lint": "1.4.0",
+ "phpstan/phpstan": "2.2.7",
+ "phpstan/phpstan-deprecation-rules": "2.0.5",
+ "phpstan/phpstan-phpunit": "2.0.18",
+ "phpstan/phpstan-strict-rules": "2.0.12",
+ "phpunit/phpunit": "9.6.34|10.5.63|11.4.4|11.5.56|12.5.33"
+ },
+ "type": "phpcodesniffer-standard",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "8.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "SlevomatCodingStandard\\": "SlevomatCodingStandard/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "description": "Slevomat Coding Standard for PHP_CodeSniffer complements Consistence Coding Standard by providing sniffs with additional checks.",
+ "keywords": [
+ "dev",
+ "phpcs"
+ ],
+ "support": {
+ "issues": "https://github.com/slevomat/coding-standard/issues",
+ "source": "https://github.com/slevomat/coding-standard/tree/8.31.1"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/kukulich",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/slevomat/coding-standard",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2026-07-31T10:42:43+00:00"
+ },
+ {
+ "name": "squizlabs/php_codesniffer",
+ "version": "4.0.4",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/PHPCSStandards/PHP_CodeSniffer.git",
+ "reference": "bbdc3d0532623e21838b7041a4364383a8126f96"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/PHPCSStandards/PHP_CodeSniffer/zipball/bbdc3d0532623e21838b7041a4364383a8126f96",
+ "reference": "bbdc3d0532623e21838b7041a4364383a8126f96",
+ "shasum": ""
+ },
+ "require": {
+ "ext-libxml": "*",
+ "ext-simplexml": "*",
+ "ext-tokenizer": "*",
+ "ext-xmlwriter": "*",
+ "php": ">=7.2.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^8.4.0 || ^9.3.4 || ^10.5.32 || 11.3.3 - 11.5.28 || ^11.5.31"
+ },
+ "suggest": {
+ "ext-iconv": "For accurate character length calculation when the checked files contain multi-byte characters.",
+ "ext-pcntl": "For parallel processing support via the --parallel CLI option."
+ },
+ "bin": [
+ "bin/phpcbf",
+ "bin/phpcs"
+ ],
+ "type": "library",
+ "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 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"
+ },
+ {
+ "url": "https://thanks.dev/u/gh/phpcsstandards",
+ "type": "thanks_dev"
+ }
+ ],
+ "time": "2026-08-06T02:45:27+00:00"
+ },
+ {
+ "name": "staabm/side-effects-detector",
+ "version": "1.0.5",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/staabm/side-effects-detector.git",
+ "reference": "d8334211a140ce329c13726d4a715adbddd0a163"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/staabm/side-effects-detector/zipball/d8334211a140ce329c13726d4a715adbddd0a163",
+ "reference": "d8334211a140ce329c13726d4a715adbddd0a163",
+ "shasum": ""
+ },
+ "require": {
+ "ext-tokenizer": "*",
+ "php": "^7.4 || ^8.0"
+ },
+ "require-dev": {
+ "phpstan/extension-installer": "^1.4.3",
+ "phpstan/phpstan": "^1.12.6",
+ "phpunit/phpunit": "^9.6.21",
+ "symfony/var-dumper": "^5.4.43",
+ "tomasvotruba/type-coverage": "1.0.0",
+ "tomasvotruba/unused-public": "1.0.0"
+ },
+ "type": "library",
+ "autoload": {
+ "classmap": [
+ "lib/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "description": "A static analysis tool to detect side effects in PHP code",
+ "keywords": [
+ "static analysis"
+ ],
+ "support": {
+ "issues": "https://github.com/staabm/side-effects-detector/issues",
+ "source": "https://github.com/staabm/side-effects-detector/tree/1.0.5"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/staabm",
+ "type": "github"
+ }
+ ],
+ "time": "2024-10-20T05:08:20+00:00"
+ },
+ {
+ "name": "symfony/yaml",
+ "version": "v7.4.15",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/yaml.git",
+ "reference": "e101850ded5d2c0d44bf32abb8996404afec2dec"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/yaml/zipball/e101850ded5d2c0d44bf32abb8996404afec2dec",
+ "reference": "e101850ded5d2c0d44bf32abb8996404afec2dec",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.2",
+ "symfony/deprecation-contracts": "^2.5|^3",
+ "symfony/polyfill-ctype": "^1.8"
+ },
+ "conflict": {
+ "symfony/console": "<6.4"
+ },
+ "require-dev": {
+ "symfony/console": "^6.4|^7.0|^8.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.4.15"
+ },
+ "funding": [
+ {
+ "url": "https://symfony.com/sponsor",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/fabpot",
+ "type": "github"
+ },
+ {
+ "url": "https://github.com/nicolas-grekas",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2026-07-21T15:13:06+00:00"
+ },
+ {
+ "name": "ta-tikoma/phpunit-architecture-test",
+ "version": "0.8.7",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/ta-tikoma/phpunit-architecture-test.git",
+ "reference": "1248f3f506ca9641d4f68cebcd538fa489754db8"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/ta-tikoma/phpunit-architecture-test/zipball/1248f3f506ca9641d4f68cebcd538fa489754db8",
+ "reference": "1248f3f506ca9641d4f68cebcd538fa489754db8",
+ "shasum": ""
+ },
+ "require": {
+ "nikic/php-parser": "^4.18.0 || ^5.0.0",
+ "php": "^8.1.0",
+ "phpdocumentor/reflection-docblock": "^5.3.0 || ^6.0.0",
+ "phpunit/phpunit": "^10.5.5 || ^11.0.0 || ^12.0.0 || ^13.0.0",
+ "symfony/finder": "^6.4.0 || ^7.0.0 || ^8.0.0"
+ },
+ "require-dev": {
+ "laravel/pint": "^1.13.7",
+ "phpstan/phpstan": "^1.10.52"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "PHPUnit\\Architecture\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Ni Shi",
+ "email": "futik0ma011@gmail.com"
+ },
+ {
+ "name": "Nuno Maduro",
+ "email": "enunomaduro@gmail.com"
+ }
+ ],
+ "description": "Methods for testing application architecture",
+ "keywords": [
+ "architecture",
+ "phpunit",
+ "stucture",
+ "test",
+ "testing"
+ ],
+ "support": {
+ "issues": "https://github.com/ta-tikoma/phpunit-architecture-test/issues",
+ "source": "https://github.com/ta-tikoma/phpunit-architecture-test/tree/0.8.7"
+ },
+ "time": "2026-02-17T17:25:14+00:00"
+ },
+ {
+ "name": "theseer/tokenizer",
+ "version": "2.0.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/theseer/tokenizer.git",
+ "reference": "7989e43bf381af0eac72e4f0ca5bcbfa81658be4"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/theseer/tokenizer/zipball/7989e43bf381af0eac72e4f0ca5bcbfa81658be4",
+ "reference": "7989e43bf381af0eac72e4f0ca5bcbfa81658be4",
+ "shasum": ""
+ },
+ "require": {
+ "ext-dom": "*",
+ "ext-tokenizer": "*",
+ "ext-xmlwriter": "*",
+ "php": "^8.1"
+ },
+ "type": "library",
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Arne Blankerts",
+ "email": "arne@blankerts.de",
+ "role": "Developer"
+ }
+ ],
+ "description": "A small library for converting tokenized PHP source code into XML and potentially other formats",
+ "support": {
+ "issues": "https://github.com/theseer/tokenizer/issues",
+ "source": "https://github.com/theseer/tokenizer/tree/2.0.1"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/theseer",
+ "type": "github"
+ }
+ ],
+ "time": "2025-12-08T11:19:18+00:00"
+ },
+ {
+ "name": "tomasvotruba/type-coverage",
+ "version": "2.3.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/TomasVotruba/type-coverage.git",
+ "reference": "7ba48c1bf3bbb7ffe99caacc7017bae5ee72d644"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/TomasVotruba/type-coverage/zipball/7ba48c1bf3bbb7ffe99caacc7017bae5ee72d644",
+ "reference": "7ba48c1bf3bbb7ffe99caacc7017bae5ee72d644",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^8.4",
+ "phpstan/phpstan": "^2.2",
+ "webmozart/assert": "^1.11 || ^2.1"
+ },
+ "require-dev": {
+ "phpstan/extension-installer": "^1.4",
+ "phpunit/phpunit": "^13.2",
+ "rector/jack": "^1.0",
+ "rector/rector": "^2.5",
+ "shipmonk/composer-dependency-analyser": "^1.8",
+ "symfony/dom-crawler": "^8.1",
+ "symplify/easy-coding-standard": "^13.2",
+ "tomasvotruba/unused-public": "^2.2",
+ "tracy/tracy": "^2.12"
+ },
+ "type": "phpstan-extension",
+ "extra": {
+ "phpstan": {
+ "includes": [
+ "config/extension.neon",
+ "packages/type-perfect/config/extension.neon"
+ ]
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Rector\\TypePerfect\\": "packages/type-perfect/src",
+ "TomasVotruba\\TypeCoverage\\": "src"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "description": "Measure type coverage of your project",
+ "keywords": [
+ "phpstan-extension",
+ "static analysis"
+ ],
+ "support": {
+ "issues": "https://github.com/TomasVotruba/type-coverage/issues",
+ "source": "https://github.com/TomasVotruba/type-coverage/tree/2.3.0"
+ },
+ "funding": [
+ {
+ "url": "https://www.paypal.me/rectorphp",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/tomasvotruba",
+ "type": "github"
+ }
+ ],
+ "time": "2026-07-29T20:32:37+00:00"
+ }
+ ],
+ "aliases": [],
+ "minimum-stability": "stable",
+ "stability-flags": {},
+ "prefer-stable": true,
+ "prefer-lowest": false,
+ "platform": {},
+ "platform-dev": {},
+ "plugin-api-version": "2.9.0"
+}
diff --git a/config/app.php b/config/app.php
new file mode 100644
index 0000000..6a88e20
--- /dev/null
+++ b/config/app.php
@@ -0,0 +1,128 @@
+ env('APP_NAME', 'Laravel'),
+
+ /*
+ |--------------------------------------------------------------------------
+ | Application Environment
+ |--------------------------------------------------------------------------
+ |
+ | This value determines the "environment" your application is currently
+ | running in. This may determine how you prefer to configure various
+ | services the application utilizes. Set this in your ".env" file.
+ |
+ */
+
+ 'env' => env('APP_ENV', 'production'),
+
+ /*
+ |--------------------------------------------------------------------------
+ | Application Debug Mode
+ |--------------------------------------------------------------------------
+ |
+ | When your application is in debug mode, detailed error messages with
+ | stack traces will be shown on every error that occurs within your
+ | application. If disabled, a simple generic error page is shown.
+ |
+ */
+
+ 'debug' => (bool) env('APP_DEBUG', false),
+
+ /*
+ |--------------------------------------------------------------------------
+ | Application URL
+ |--------------------------------------------------------------------------
+ |
+ | This URL is used by the console to properly generate URLs when using
+ | the Artisan command line tool. You should set this to the root of
+ | the application so that it's available within Artisan commands.
+ |
+ */
+
+ 'url' => env('APP_URL', 'http://localhost'),
+
+ /*
+ |--------------------------------------------------------------------------
+ | Application Timezone
+ |--------------------------------------------------------------------------
+ |
+ | Here you may specify the default timezone for your application, which
+ | will be used by the PHP date and date-time functions. The timezone
+ | is set to "UTC" by default as it is suitable for most use cases.
+ |
+ */
+
+ 'timezone' => 'UTC',
+
+ /*
+ |--------------------------------------------------------------------------
+ | Application Locale Configuration
+ |--------------------------------------------------------------------------
+ |
+ | The application locale determines the default locale that will be used
+ | by Laravel's translation / localization methods. This option can be
+ | set to any locale for which you plan to have translation strings.
+ |
+ */
+
+ 'locale' => env('APP_LOCALE', 'en'),
+
+ 'fallback_locale' => env('APP_FALLBACK_LOCALE', 'en'),
+
+ 'faker_locale' => env('APP_FAKER_LOCALE', 'en_US'),
+
+ /*
+ |--------------------------------------------------------------------------
+ | Encryption Key
+ |--------------------------------------------------------------------------
+ |
+ | This key is utilized by Laravel's encryption services and should be set
+ | to a random, 32 character string to ensure that all encrypted values
+ | are secure. You should do this prior to deploying the application.
+ |
+ */
+
+ 'cipher' => 'AES-256-CBC',
+
+ 'key' => env('APP_KEY'),
+
+ 'previous_keys' => [
+ ...array_filter(
+ explode(',', (string) env('APP_PREVIOUS_KEYS', ''))
+ ),
+ ],
+
+ /*
+ |--------------------------------------------------------------------------
+ | Maintenance Mode Driver
+ |--------------------------------------------------------------------------
+ |
+ | These configuration options determine the driver used to determine and
+ | manage Laravel's "maintenance mode" status. The "cache" driver will
+ | allow maintenance mode to be controlled across multiple machines.
+ |
+ | Supported drivers: "file", "cache"
+ |
+ */
+
+ 'maintenance' => [
+ 'driver' => env('APP_MAINTENANCE_DRIVER', 'file'),
+ 'store' => env('APP_MAINTENANCE_STORE', 'database'),
+ ],
+
+];
diff --git a/config/auth.php b/config/auth.php
new file mode 100644
index 0000000..5710a70
--- /dev/null
+++ b/config/auth.php
@@ -0,0 +1,119 @@
+ [
+ 'guard' => env('AUTH_GUARD', 'web'),
+ 'passwords' => env('AUTH_PASSWORD_BROKER', 'users'),
+ ],
+
+ /*
+ |--------------------------------------------------------------------------
+ | Authentication Guards
+ |--------------------------------------------------------------------------
+ |
+ | Next, you may define every authentication guard for your application.
+ | Of course, a great default configuration has been defined for you
+ | which utilizes session storage plus the Eloquent user provider.
+ |
+ | All authentication guards have a user provider, which defines how the
+ | users are actually retrieved out of your database or other storage
+ | system used by the application. Typically, Eloquent is utilized.
+ |
+ | Supported: "session"
+ |
+ */
+
+ 'guards' => [
+ 'web' => [
+ 'driver' => 'session',
+ 'provider' => 'users',
+ ],
+ ],
+
+ /*
+ |--------------------------------------------------------------------------
+ | User Providers
+ |--------------------------------------------------------------------------
+ |
+ | All authentication guards have a user provider, which defines how the
+ | users are actually retrieved out of your database or other storage
+ | system used by the application. Typically, Eloquent is utilized.
+ |
+ | If you have multiple user tables or models you may configure multiple
+ | providers to represent the model / table. These providers may then
+ | be assigned to any extra authentication guards you have defined.
+ |
+ | Supported: "database", "eloquent"
+ |
+ */
+
+ 'providers' => [
+ 'users' => [
+ 'driver' => 'eloquent',
+ 'model' => env('AUTH_MODEL', User::class),
+ ],
+
+ // 'users' => [
+ // 'driver' => 'database',
+ // 'table' => 'users',
+ // ],
+ ],
+
+ /*
+ |--------------------------------------------------------------------------
+ | Resetting Passwords
+ |--------------------------------------------------------------------------
+ |
+ | These configuration options specify the behavior of Laravel's password
+ | reset functionality, including the table utilized for token storage
+ | and the user provider that is invoked to actually retrieve users.
+ |
+ | The expiry time is the number of minutes that each reset token will be
+ | considered valid. This security feature keeps tokens short-lived so
+ | they have less time to be guessed. You may change this as needed.
+ |
+ | The throttle setting is the number of seconds a user must wait before
+ | generating more password reset tokens. This prevents the user from
+ | quickly generating a very large amount of password reset tokens.
+ |
+ */
+
+ 'passwords' => [
+ 'users' => [
+ 'provider' => 'users',
+ 'table' => env('AUTH_PASSWORD_RESET_TOKEN_TABLE', 'password_reset_tokens'),
+ 'expire' => 60,
+ 'throttle' => 60,
+ ],
+ ],
+
+ /*
+ |--------------------------------------------------------------------------
+ | Password Confirmation Timeout
+ |--------------------------------------------------------------------------
+ |
+ | Here you may define the number of seconds before a password confirmation
+ | window expires and users are asked to re-enter their password via the
+ | confirmation screen. By default, the timeout lasts for three hours.
+ |
+ */
+
+ 'password_timeout' => env('AUTH_PASSWORD_TIMEOUT', 10800),
+
+];
diff --git a/config/cache.php b/config/cache.php
new file mode 100644
index 0000000..a28f5fa
--- /dev/null
+++ b/config/cache.php
@@ -0,0 +1,138 @@
+ env('CACHE_STORE', 'database'),
+
+ /*
+ |--------------------------------------------------------------------------
+ | Cache Stores
+ |--------------------------------------------------------------------------
+ |
+ | Here you may define all of the cache "stores" for your application as
+ | well as their drivers. You may even define multiple stores for the
+ | same cache driver to group types of items stored in your caches.
+ |
+ | Supported drivers: "array", "database", "file", "memcached",
+ | "redis", "dynamodb", "storage", "octane",
+ | "session", "failover", "null"
+ |
+ */
+
+ 'stores' => [
+
+ 'array' => [
+ 'driver' => 'array',
+ 'serialize' => false,
+ ],
+
+ 'database' => [
+ 'driver' => 'database',
+ 'connection' => env('DB_CACHE_CONNECTION'),
+ 'table' => env('DB_CACHE_TABLE', 'cache'),
+ 'lock_connection' => env('DB_CACHE_LOCK_CONNECTION'),
+ 'lock_table' => env('DB_CACHE_LOCK_TABLE'),
+ ],
+
+ 'file' => [
+ 'driver' => 'file',
+ 'path' => storage_path('framework/cache/data'),
+ 'lock_path' => storage_path('framework/cache/data'),
+ ],
+
+ 'storage' => [
+ 'driver' => 'storage',
+ 'disk' => env('CACHE_STORAGE_DISK'),
+ 'path' => env('CACHE_STORAGE_PATH', 'framework/cache/data'),
+ ],
+
+ 'memcached' => [
+ 'driver' => 'memcached',
+ 'persistent_id' => env('MEMCACHED_PERSISTENT_ID'),
+ 'sasl' => [
+ env('MEMCACHED_USERNAME'),
+ env('MEMCACHED_PASSWORD'),
+ ],
+ 'options' => [
+ // Memcached::OPT_CONNECT_TIMEOUT => 2000,
+ ],
+ 'servers' => [
+ [
+ 'host' => env('MEMCACHED_HOST', '127.0.0.1'),
+ 'port' => env('MEMCACHED_PORT', 11211),
+ 'weight' => 100,
+ ],
+ ],
+ ],
+
+ 'redis' => [
+ 'driver' => 'redis',
+ 'connection' => env('REDIS_CACHE_CONNECTION', 'cache'),
+ 'lock_connection' => env('REDIS_CACHE_LOCK_CONNECTION', 'default'),
+ ],
+
+ 'dynamodb' => [
+ 'driver' => 'dynamodb',
+ 'key' => env('AWS_ACCESS_KEY_ID'),
+ 'secret' => env('AWS_SECRET_ACCESS_KEY'),
+ 'region' => env('AWS_DEFAULT_REGION', 'us-east-1'),
+ 'table' => env('DYNAMODB_CACHE_TABLE', 'cache'),
+ 'endpoint' => env('DYNAMODB_ENDPOINT'),
+ ],
+
+ 'octane' => [
+ 'driver' => 'octane',
+ ],
+
+ 'failover' => [
+ 'driver' => 'failover',
+ 'stores' => [
+ 'database',
+ 'array',
+ ],
+ ],
+
+ ],
+
+ /*
+ |--------------------------------------------------------------------------
+ | Cache Key Prefix
+ |--------------------------------------------------------------------------
+ |
+ | When utilizing the APC, database, memcached, Redis, and DynamoDB cache
+ | stores, there might be other applications using the same cache. For
+ | that reason, you may prefix every cache key to avoid collisions.
+ |
+ */
+
+ 'prefix' => env('CACHE_PREFIX', Str::slug((string) env('APP_NAME', 'laravel')) . '-cache-'),
+
+ /*
+ |--------------------------------------------------------------------------
+ | Serializable Classes
+ |--------------------------------------------------------------------------
+ |
+ | This value determines the classes that can be unserialized from cache
+ | storage. By default, no PHP classes will be unserialized from your
+ | cache to prevent gadget chain attacks if your APP_KEY is leaked.
+ |
+ */
+
+ 'serializable_classes' => false,
+
+];
diff --git a/config/database.php b/config/database.php
new file mode 100644
index 0000000..62d8f79
--- /dev/null
+++ b/config/database.php
@@ -0,0 +1,208 @@
+ env('DB_CONNECTION', 'sqlite'),
+
+ 'arcadia_meta_model' => env('ARCADIA_DB_CONNECTION', 'arcadia'),
+
+ /*
+ |--------------------------------------------------------------------------
+ | Database Connections
+ |--------------------------------------------------------------------------
+ |
+ | Below are all of the database connections defined for your application.
+ | An example configuration is provided for each database system which
+ | is supported by Laravel. You're free to add / remove connections.
+ |
+ */
+
+ 'connections' => [
+
+ 'arcadia' => [
+ 'driver' => 'mariadb',
+ 'url' => env('ARCADIA_DB_URL'),
+ 'host' => env('ARCADIA_DB_HOST', '127.0.0.1'),
+ 'port' => env('ARCADIA_DB_PORT', '3306'),
+ 'database' => env('ARCADIA_DB', 'arcadia'),
+ 'username' => env('ARCADIA_DB_USERNAME', 'root'),
+ 'password' => env('ARCADIA_DB_PASSWORD', ''),
+ 'unix_socket' => env('ARCADIA_DB_SOCKET', ''),
+ 'charset' => env('ARCADIA_DB_CHARSET', 'utf8mb4'),
+ 'collation' => env('ARCADIA_DB_COLLATION', 'utf8mb4_unicode_ci'),
+ 'prefix' => '',
+ 'prefix_indexes' => true,
+ 'strict' => true,
+ 'engine' => null,
+ 'options' => extension_loaded('pdo_mysql') ? array_filter([
+ Mysql::ATTR_SSL_CA => env('ARCADIA_DB_SSL_CA'),
+ ]) : [],
+ ],
+
+ 'sqlite' => [
+ 'driver' => 'sqlite',
+ 'url' => env('DB_URL'),
+ 'database' => env('DB_DATABASE', database_path('database.sqlite')),
+ 'prefix' => '',
+ 'foreign_key_constraints' => env('DB_FOREIGN_KEYS', true),
+ 'busy_timeout' => null,
+ 'journal_mode' => null,
+ 'synchronous' => null,
+ 'transaction_mode' => 'DEFERRED',
+ ],
+
+ 'mysql' => [
+ 'driver' => 'mysql',
+ 'url' => env('DB_URL'),
+ 'host' => env('DB_HOST', '127.0.0.1'),
+ 'port' => env('DB_PORT', '3306'),
+ 'database' => env('DB_DATABASE', 'laravel'),
+ 'username' => env('DB_USERNAME', 'root'),
+ 'password' => env('DB_PASSWORD', ''),
+ 'unix_socket' => env('DB_SOCKET', ''),
+ 'charset' => env('DB_CHARSET', 'utf8mb4'),
+ 'collation' => env('DB_COLLATION', 'utf8mb4_unicode_ci'),
+ 'prefix' => '',
+ 'prefix_indexes' => true,
+ 'strict' => true,
+ 'engine' => null,
+ 'options' => extension_loaded('pdo_mysql') ? array_filter([
+ Mysql::ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'),
+ ]) : [],
+ ],
+
+ 'mariadb' => [
+ 'driver' => 'mariadb',
+ 'url' => env('DB_URL'),
+ 'host' => env('DB_HOST', '127.0.0.1'),
+ 'port' => env('DB_PORT', '3306'),
+ 'database' => env('DB_DATABASE', 'laravel'),
+ 'username' => env('DB_USERNAME', 'root'),
+ 'password' => env('DB_PASSWORD', ''),
+ 'unix_socket' => env('DB_SOCKET', ''),
+ 'charset' => env('DB_CHARSET', 'utf8mb4'),
+ 'collation' => env('DB_COLLATION', 'utf8mb4_unicode_ci'),
+ 'prefix' => '',
+ 'prefix_indexes' => true,
+ 'strict' => true,
+ 'engine' => null,
+ 'options' => extension_loaded('pdo_mysql') ? array_filter([
+ Mysql::ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'),
+ ]) : [],
+ ],
+
+ 'pgsql' => [
+ 'driver' => 'pgsql',
+ 'url' => env('DB_URL'),
+ 'host' => env('DB_HOST', '127.0.0.1'),
+ 'port' => env('DB_PORT', '5432'),
+ 'database' => env('DB_DATABASE', 'laravel'),
+ 'username' => env('DB_USERNAME', 'root'),
+ 'password' => env('DB_PASSWORD', ''),
+ 'charset' => env('DB_CHARSET', 'utf8'),
+ 'prefix' => '',
+ 'prefix_indexes' => true,
+ 'search_path' => 'public',
+ 'sslmode' => env('DB_SSLMODE', 'prefer'),
+ ],
+
+ 'sqlsrv' => [
+ 'driver' => 'sqlsrv',
+ 'url' => env('DB_URL'),
+ 'host' => env('DB_HOST', 'localhost'),
+ 'port' => env('DB_PORT', '1433'),
+ 'database' => env('DB_DATABASE', 'laravel'),
+ 'username' => env('DB_USERNAME', 'root'),
+ 'password' => env('DB_PASSWORD', ''),
+ 'charset' => env('DB_CHARSET', 'utf8'),
+ 'prefix' => '',
+ 'prefix_indexes' => true,
+ // 'encrypt' => env('DB_ENCRYPT', 'yes'),
+ // 'trust_server_certificate' => env('DB_TRUST_SERVER_CERTIFICATE', 'false'),
+ ],
+
+ ],
+
+ /*
+ |--------------------------------------------------------------------------
+ | Migration Repository Table
+ |--------------------------------------------------------------------------
+ |
+ | This table keeps track of all the migrations that have already run for
+ | your application. Using this information, we can determine which of
+ | the migrations on disk haven't actually been run on the database.
+ |
+ */
+
+ 'migrations' => [
+ 'table' => 'migrations',
+ 'update_date_on_publish' => true,
+ ],
+
+ /*
+ |--------------------------------------------------------------------------
+ | Redis Databases
+ |--------------------------------------------------------------------------
+ |
+ | Redis is an open source, fast, and advanced key-value store that also
+ | provides a richer body of commands than a typical key-value system
+ | such as Memcached. You may define your connection settings here.
+ |
+ */
+
+ 'redis' => [
+
+ 'client' => env('REDIS_CLIENT', 'phpredis'),
+
+ 'options' => [
+ 'cluster' => env('REDIS_CLUSTER', 'redis'),
+ 'prefix' => env('REDIS_PREFIX', Str::slug((string) env('APP_NAME', 'laravel')) . '-database-'),
+ 'persistent' => env('REDIS_PERSISTENT', false),
+ ],
+
+ 'default' => [
+ 'url' => env('REDIS_URL'),
+ 'host' => env('REDIS_HOST', '127.0.0.1'),
+ 'username' => env('REDIS_USERNAME'),
+ 'password' => env('REDIS_PASSWORD'),
+ 'port' => env('REDIS_PORT', '6379'),
+ 'database' => env('REDIS_DB', '0'),
+ 'max_retries' => env('REDIS_MAX_RETRIES', 3),
+ 'backoff_algorithm' => env('REDIS_BACKOFF_ALGORITHM', 'decorrelated_jitter'),
+ 'backoff_base' => env('REDIS_BACKOFF_BASE', 100),
+ 'backoff_cap' => env('REDIS_BACKOFF_CAP', 1000),
+ ],
+
+ 'cache' => [
+ 'url' => env('REDIS_URL'),
+ 'host' => env('REDIS_HOST', '127.0.0.1'),
+ 'username' => env('REDIS_USERNAME'),
+ 'password' => env('REDIS_PASSWORD'),
+ 'port' => env('REDIS_PORT', '6379'),
+ 'database' => env('REDIS_CACHE_DB', '1'),
+ 'max_retries' => env('REDIS_MAX_RETRIES', 3),
+ 'backoff_algorithm' => env('REDIS_BACKOFF_ALGORITHM', 'decorrelated_jitter'),
+ 'backoff_base' => env('REDIS_BACKOFF_BASE', 100),
+ 'backoff_cap' => env('REDIS_BACKOFF_CAP', 1000),
+ ],
+
+ ],
+
+];
diff --git a/config/filesystems.php b/config/filesystems.php
new file mode 100644
index 0000000..54471c0
--- /dev/null
+++ b/config/filesystems.php
@@ -0,0 +1,82 @@
+ env('FILESYSTEM_DISK', 'local'),
+
+ /*
+ |--------------------------------------------------------------------------
+ | Filesystem Disks
+ |--------------------------------------------------------------------------
+ |
+ | Below you may configure as many filesystem disks as necessary, and you
+ | may even configure multiple disks for the same driver. Examples for
+ | most supported storage drivers are configured here for reference.
+ |
+ | Supported drivers: "local", "ftp", "sftp", "s3"
+ |
+ */
+
+ 'disks' => [
+
+ 'local' => [
+ 'driver' => 'local',
+ 'root' => storage_path('app/private'),
+ 'serve' => true,
+ 'throw' => false,
+ 'report' => false,
+ ],
+
+ 'public' => [
+ 'driver' => 'local',
+ 'root' => storage_path('app/public'),
+ 'url' => rtrim(env('APP_URL', 'http://localhost'), '/') . '/storage',
+ 'visibility' => 'public',
+ 'throw' => false,
+ 'report' => false,
+ ],
+
+ 's3' => [
+ 'driver' => 's3',
+ 'key' => env('AWS_ACCESS_KEY_ID'),
+ 'secret' => env('AWS_SECRET_ACCESS_KEY'),
+ 'region' => env('AWS_DEFAULT_REGION'),
+ 'bucket' => env('AWS_BUCKET'),
+ 'url' => env('AWS_URL'),
+ 'endpoint' => env('AWS_ENDPOINT'),
+ 'use_path_style_endpoint' => env('AWS_USE_PATH_STYLE_ENDPOINT', false),
+ 'throw' => false,
+ 'report' => false,
+ ],
+
+ ],
+
+ /*
+ |--------------------------------------------------------------------------
+ | Symbolic Links
+ |--------------------------------------------------------------------------
+ |
+ | Here you may configure the symbolic links that will be created when the
+ | `storage:link` Artisan command is executed. The array keys should be
+ | the locations of the links and the values should be their targets.
+ |
+ */
+
+ 'links' => [
+ public_path('storage') => storage_path('app/public'),
+ ],
+
+];
diff --git a/config/ide-helper.php b/config/ide-helper.php
new file mode 100644
index 0000000..c820bfa
--- /dev/null
+++ b/config/ide-helper.php
@@ -0,0 +1,379 @@
+ '_ide_helper.php',
+
+ /*
+ |--------------------------------------------------------------------------
+ | Models filename
+ |--------------------------------------------------------------------------
+ |
+ | The default filename for the models helper file.
+ |
+ */
+
+ 'models_filename' => '_ide_helper_models.php',
+
+ /*
+ |--------------------------------------------------------------------------
+ | PhpStorm meta filename
+ |--------------------------------------------------------------------------
+ |
+ | PhpStorm also supports the directory `.phpstorm.meta.php/` with arbitrary
+ | files in it, should you need additional files for your project; e.g.
+ | `.phpstorm.meta.php/laravel_ide_Helper.php'.
+ |
+ */
+ 'meta_filename' => '.phpstorm.meta.php',
+
+ /*
+ |--------------------------------------------------------------------------
+ | Fluent helpers
+ |--------------------------------------------------------------------------
+ |
+ | Set to true to generate commonly used Fluent methods.
+ |
+ */
+
+ 'include_fluent' => false,
+
+ /*
+ |--------------------------------------------------------------------------
+ | Write model query methods
+ |--------------------------------------------------------------------------
+ |
+ | Set to false to disable generated docs for the 'query()', 'newQuery()' and 'newModelQuery()' methods.
+ |
+ */
+
+ 'write_query_methods' => false,
+
+ /*
+ |--------------------------------------------------------------------------
+ | Write model magic methods
+ |--------------------------------------------------------------------------
+ |
+ | Set to false to disable write magic methods of model.
+ |
+ */
+
+ 'write_model_magic_where' => false,
+
+ /*
+ |--------------------------------------------------------------------------
+ | Write model external Eloquent builder methods
+ |--------------------------------------------------------------------------
+ |
+ | Set to false to disable write external Eloquent builder methods.
+ |
+ */
+
+ 'write_model_external_builder_methods' => false,
+
+ /*
+ |--------------------------------------------------------------------------
+ | Write model relation count and exists properties
+ |--------------------------------------------------------------------------
+ |
+ | Set to false to disable writing of relation count and exists properties
+ | to model DocBlocks.
+ |
+ */
+
+ 'write_model_relation_count_properties' => false,
+ 'write_model_relation_exists_properties' => false,
+
+ /*
+ |--------------------------------------------------------------------------
+ | Write Eloquent model mixins
+ |--------------------------------------------------------------------------
+ |
+ | This will add the necessary DocBlock mixins to the model class
+ | contained in the Laravel framework. This helps the IDE with
+ | auto-completion.
+ |
+ | Please be aware that this setting changes a file within the /vendor directory.
+ |
+ */
+
+ 'write_eloquent_model_mixins' => false,
+
+ /*
+ |--------------------------------------------------------------------------
+ | Helper files to include
+ |--------------------------------------------------------------------------
+ |
+ | Include helper files. By default not included, but can be toggled with the
+ | -- helpers (-H) option. Extra helper files can be included.
+ |
+ */
+
+ 'include_helpers' => false,
+
+ 'helper_files' => [
+ base_path() . '/vendor/laravel/framework/src/Illuminate/Support/helpers.php',
+ base_path() . '/vendor/laravel/framework/src/Illuminate/Foundation/helpers.php',
+ ],
+
+ /*
+ |--------------------------------------------------------------------------
+ | Model locations to include
+ |--------------------------------------------------------------------------
+ |
+ | Define in which directories the ide-helper:models command should look
+ | for models.
+ |
+ | glob patterns are supported to easier reach models in sub-directories,
+ | e.g. `app/Services/* /Models` (without the space).
+ |
+ */
+
+ 'model_locations' => [
+ 'src/Presentation',
+ ],
+
+ /*
+ |--------------------------------------------------------------------------
+ | Models to ignore
+ |--------------------------------------------------------------------------
+ |
+ | Define which models should be ignored.
+ |
+ */
+
+ 'ignored_models' => [],
+
+ /*
+ |--------------------------------------------------------------------------
+ | Models hooks
+ |--------------------------------------------------------------------------
+ |
+ | Define which hook classes you want to run for models to add custom information.
+ |
+ | Hooks should implement Barryvdh\LaravelIdeHelper\Contracts\ModelHookInterface.
+ |
+ */
+
+ 'model_hooks' => [
+ // App\Support\IdeHelper\MyModelHook::class
+ ],
+
+ /*
+ |--------------------------------------------------------------------------
+ | Extra classes
+ |--------------------------------------------------------------------------
+ |
+ | These implementations are not really extended, but called with magic functions.
+ |
+ */
+
+ 'extra' => [
+ 'Eloquent' => [Builder::class, \Illuminate\Database\Query\Builder::class],
+ 'Session' => [Store::class],
+ ],
+
+ 'magic' => [],
+
+ /*
+ |--------------------------------------------------------------------------
+ | Interface implementations
+ |--------------------------------------------------------------------------
+ |
+ | These interfaces will be replaced with the implementing class. Some interfaces
+ | are detected by the helpers, others can be listed below.
+ |
+ */
+
+ 'interfaces' => [
+ // App\MyInterface::class => App\MyImplementation::class,
+ ],
+
+ /*
+ |--------------------------------------------------------------------------
+ | Support for camel cased models
+ |--------------------------------------------------------------------------
+ |
+ | There are some Laravel packages (such as Eloquence) that allow for accessing
+ | Eloquent model properties via camel case, instead of snake case.
+ |
+ | Enabling this option will support these packages by saving all model
+ | properties as camel case, instead of snake case.
+ |
+ | For example, normally you would see this:
+ |
+ | * @property \Illuminate\Support\Carbon $created_at
+ | * @property \Illuminate\Support\Carbon $updated_at
+ |
+ | With this enabled, the properties will be this:
+ |
+ | * @property \Illuminate\Support\Carbon $createdAt
+ | * @property \Illuminate\Support\Carbon $updatedAt
+ |
+ | Note, it is currently an all-or-nothing option.
+ |
+ */
+ 'model_camel_case_properties' => false,
+
+ /*
+ |--------------------------------------------------------------------------
+ | Property casts
+ |--------------------------------------------------------------------------
+ |
+ | Cast the given "real type" to the given "type".
+ |
+ */
+ 'type_overrides' => [
+ 'integer' => 'int',
+ 'boolean' => 'bool',
+ ],
+
+ /*
+ |--------------------------------------------------------------------------
+ | Include DocBlocks from classes
+ |--------------------------------------------------------------------------
+ |
+ | Include DocBlocks from classes to allow additional code inspection for
+ | magic methods and properties.
+ |
+ */
+ 'include_class_docblocks' => false,
+
+ /*
+ |--------------------------------------------------------------------------
+ | Force FQN usage
+ |--------------------------------------------------------------------------
+ |
+ | Use the fully qualified (class) name in DocBlocks,
+ | even if the class exists in the same namespace
+ | or there is an import (use className) of the class.
+ |
+ */
+ 'force_fqn' => false,
+
+ /*
+ |--------------------------------------------------------------------------
+ | Use generics syntax
+ |--------------------------------------------------------------------------
+ |
+ | Use generics syntax within DocBlocks,
+ | e.g. `Collection` instead of `Collection|User[]`.
+ |
+ */
+ 'use_generics_annotations' => true,
+
+ /*
+ |--------------------------------------------------------------------------
+ | Default return types for macros
+ |--------------------------------------------------------------------------
+ |
+ | Define default return types for macros without explicit return types.
+ | e.g. `\Illuminate\Database\Query\Builder::class => 'static'`,
+ | `\Illuminate\Support\Str::class => 'string'`
+ |
+ */
+ 'macro_default_return_types' => [
+ Factory::class => PendingRequest::class,
+ ],
+
+ /*
+ |--------------------------------------------------------------------------
+ | Additional relation types
+ |--------------------------------------------------------------------------
+ |
+ | Sometimes it's needed to create custom relation types. The key of the array
+ | is the relationship method name. The value of the array is the fully-qualified
+ | class name of the relationship, e.g. `'relationName' => RelationShipClass::class`.
+ |
+ */
+ 'additional_relation_types' => [],
+
+ /*
+ |--------------------------------------------------------------------------
+ | Additional relation return types
+ |--------------------------------------------------------------------------
+ |
+ | When using custom relation types its possible for the class name to not contain
+ | the proper return type of the relation. The key of the array is the relationship
+ | method name. The value of the array is the return type of the relation ('many'
+ | or 'morphTo').
+ | e.g. `'relationName' => 'many'`.
+ |
+ */
+ 'additional_relation_return_types' => [],
+
+ /*
+ |--------------------------------------------------------------------------
+ | Enforce nullable Eloquent relationships on not null columns
+ |--------------------------------------------------------------------------
+ |
+ | When set to true (default), this option enforces nullable Eloquent relationships.
+ | However, in cases where the application logic ensures the presence of related
+ | records it may be desirable to set this option to false to avoid unwanted null warnings.
+ |
+ | Default: true
+ | A not null column with no foreign key constraint will have a "nullable" relationship.
+ | * @property int $not_null_column_with_no_foreign_key_constraint
+ | * @property-read BelongsToVariation|null $notNullColumnWithNoForeignKeyConstraint
+ |
+ | Option: false
+ | A not null column with no foreign key constraint will have a "not nullable" relationship.
+ | * @property int $not_null_column_with_no_foreign_key_constraint
+ | * @property-read BelongsToVariation $notNullColumnWithNoForeignKeyConstraint
+ |
+ */
+
+ 'enforce_nullable_relationships' => true,
+
+ /*
+ |--------------------------------------------------------------------------
+ | Make soft deletable relations nullable
+ |--------------------------------------------------------------------------
+ |
+ | When set to true (default), relationships to models using SoftDeletes trait
+ | will be marked as nullable. This is because soft-deleted records are excluded
+ | from queries by default, meaning even non-nullable foreign keys can return
+ | null when the related model is soft-deleted.
+ |
+ | Default: true
+ | A relationship to a soft-deletable model will include |null in the type:
+ | * @property-read Team|null $team
+ |
+ | Option: false
+ | A relationship to a soft-deletable model will NOT include |null (unless
+ | nullable for other reasons such as nullable foreign key column):
+ | * @property-read Team $team
+ |
+ */
+
+ 'soft_deletes_force_nullable' => true,
+
+ /*
+ |--------------------------------------------------------------------------
+ | Run artisan commands after migrations to generate model helpers
+ |--------------------------------------------------------------------------
+ |
+ | The specified commands should run after migrations are finished running.
+ |
+ */
+ 'post_migrate' => [
+ // 'ide-helper:models --nowrite',
+ ],
+
+];
diff --git a/config/logging.php b/config/logging.php
new file mode 100644
index 0000000..d738574
--- /dev/null
+++ b/config/logging.php
@@ -0,0 +1,134 @@
+ env('LOG_CHANNEL', 'stack'),
+
+ /*
+ |--------------------------------------------------------------------------
+ | Deprecations Log Channel
+ |--------------------------------------------------------------------------
+ |
+ | This option controls the log channel that should be used to log warnings
+ | regarding deprecated PHP and library features. This allows you to get
+ | your application ready for upcoming major versions of dependencies.
+ |
+ */
+
+ 'deprecations' => [
+ 'channel' => env('LOG_DEPRECATIONS_CHANNEL', 'null'),
+ 'trace' => env('LOG_DEPRECATIONS_TRACE', false),
+ ],
+
+ /*
+ |--------------------------------------------------------------------------
+ | Log Channels
+ |--------------------------------------------------------------------------
+ |
+ | Here you may configure the log channels for your application. Laravel
+ | utilizes the Monolog PHP logging library, which includes a variety
+ | of powerful log handlers and formatters that you're free to use.
+ |
+ | Available drivers: "single", "daily", "slack", "syslog",
+ | "errorlog", "monolog", "custom", "stack"
+ |
+ */
+
+ 'channels' => [
+
+ 'stack' => [
+ 'driver' => 'stack',
+ 'channels' => explode(',', (string) env('LOG_STACK', 'single')),
+ 'ignore_exceptions' => false,
+ ],
+
+ 'single' => [
+ 'driver' => 'single',
+ 'path' => storage_path('logs/laravel.log'),
+ 'level' => env('LOG_LEVEL', 'debug'),
+ 'replace_placeholders' => true,
+ ],
+
+ 'daily' => [
+ 'driver' => 'daily',
+ 'path' => storage_path('logs/laravel.log'),
+ 'level' => env('LOG_LEVEL', 'debug'),
+ 'days' => env('LOG_DAILY_DAYS', 14),
+ 'replace_placeholders' => true,
+ ],
+
+ 'slack' => [
+ 'driver' => 'slack',
+ 'url' => env('LOG_SLACK_WEBHOOK_URL'),
+ 'username' => env('LOG_SLACK_USERNAME', env('APP_NAME', 'Laravel')),
+ 'emoji' => env('LOG_SLACK_EMOJI', ':boom:'),
+ 'level' => env('LOG_LEVEL', 'critical'),
+ 'replace_placeholders' => true,
+ ],
+
+ 'papertrail' => [
+ 'driver' => 'monolog',
+ 'level' => env('LOG_LEVEL', 'debug'),
+ 'handler' => env('LOG_PAPERTRAIL_HANDLER', SyslogUdpHandler::class),
+ 'handler_with' => [
+ 'host' => env('PAPERTRAIL_URL'),
+ 'port' => env('PAPERTRAIL_PORT'),
+ 'connectionString' => 'tls://' . env('PAPERTRAIL_URL') . ':' . env('PAPERTRAIL_PORT'),
+ ],
+ 'processors' => [PsrLogMessageProcessor::class],
+ ],
+
+ 'stderr' => [
+ 'driver' => 'monolog',
+ 'level' => env('LOG_LEVEL', 'debug'),
+ 'handler' => StreamHandler::class,
+ 'handler_with' => [
+ 'stream' => 'php://stderr',
+ ],
+ 'formatter' => env('LOG_STDERR_FORMATTER'),
+ 'processors' => [PsrLogMessageProcessor::class],
+ ],
+
+ 'syslog' => [
+ 'driver' => 'syslog',
+ 'level' => env('LOG_LEVEL', 'debug'),
+ 'facility' => env('LOG_SYSLOG_FACILITY', LOG_USER),
+ 'replace_placeholders' => true,
+ ],
+
+ 'errorlog' => [
+ 'driver' => 'errorlog',
+ 'level' => env('LOG_LEVEL', 'debug'),
+ 'replace_placeholders' => true,
+ ],
+
+ 'null' => [
+ 'driver' => 'monolog',
+ 'handler' => NullHandler::class,
+ ],
+
+ 'emergency' => [
+ 'path' => storage_path('logs/laravel.log'),
+ ],
+
+ ],
+
+];
diff --git a/config/mail.php b/config/mail.php
new file mode 100644
index 0000000..36da1fb
--- /dev/null
+++ b/config/mail.php
@@ -0,0 +1,120 @@
+ env('MAIL_MAILER', 'log'),
+
+ /*
+ |--------------------------------------------------------------------------
+ | Mailer Configurations
+ |--------------------------------------------------------------------------
+ |
+ | Here you may configure all of the mailers used by your application plus
+ | their respective settings. Several examples have been configured for
+ | you and you are free to add your own as your application requires.
+ |
+ | Laravel supports a variety of mail "transport" drivers that can be used
+ | when delivering an email. You may specify which one you're using for
+ | your mailers below. You may also add additional mailers if needed.
+ |
+ | Supported: "smtp", "sendmail", "mailgun", "ses", "ses-v2",
+ | "postmark", "resend", "log", "array",
+ | "failover", "roundrobin"
+ |
+ */
+
+ 'mailers' => [
+
+ 'smtp' => [
+ 'transport' => 'smtp',
+ 'scheme' => env('MAIL_SCHEME'),
+ 'url' => env('MAIL_URL'),
+ 'host' => env('MAIL_HOST', '127.0.0.1'),
+ 'port' => env('MAIL_PORT', 2525),
+ 'username' => env('MAIL_USERNAME'),
+ 'password' => env('MAIL_PASSWORD'),
+ 'timeout' => null,
+ 'local_domain' => env('MAIL_EHLO_DOMAIN', parse_url((string) env('APP_URL', 'http://localhost'), PHP_URL_HOST)),
+ ],
+
+ 'ses' => [
+ 'transport' => 'ses',
+ ],
+
+ 'postmark' => [
+ 'transport' => 'postmark',
+ // 'message_stream_id' => env('POSTMARK_MESSAGE_STREAM_ID'),
+ // 'client' => [
+ // 'timeout' => 5,
+ // ],
+ ],
+
+ 'resend' => [
+ 'transport' => 'resend',
+ ],
+
+ 'sendmail' => [
+ 'transport' => 'sendmail',
+ 'path' => env('MAIL_SENDMAIL_PATH', '/usr/sbin/sendmail -bs -i'),
+ ],
+
+ 'log' => [
+ 'transport' => 'log',
+ 'channel' => env('MAIL_LOG_CHANNEL'),
+ ],
+
+ 'array' => [
+ 'transport' => 'array',
+ ],
+
+ 'failover' => [
+ 'transport' => 'failover',
+ 'mailers' => [
+ 'smtp',
+ 'log',
+ ],
+ 'retry_after' => 60,
+ ],
+
+ 'roundrobin' => [
+ 'transport' => 'roundrobin',
+ 'mailers' => [
+ 'ses',
+ 'postmark',
+ ],
+ 'retry_after' => 60,
+ ],
+
+ ],
+
+ /*
+ |--------------------------------------------------------------------------
+ | Global "From" Address
+ |--------------------------------------------------------------------------
+ |
+ | You may wish for all emails sent by your application to be sent from
+ | the same address. Here you may specify a name and address that is
+ | used globally for all emails that are sent by your application.
+ |
+ */
+
+ 'from' => [
+ 'address' => env('MAIL_FROM_ADDRESS', 'hello@example.com'),
+ 'name' => env('MAIL_FROM_NAME', env('APP_NAME', 'Laravel')),
+ ],
+
+];
diff --git a/config/queue.php b/config/queue.php
new file mode 100644
index 0000000..c5bc727
--- /dev/null
+++ b/config/queue.php
@@ -0,0 +1,131 @@
+ env('QUEUE_CONNECTION', 'database'),
+
+ /*
+ |--------------------------------------------------------------------------
+ | Queue Connections
+ |--------------------------------------------------------------------------
+ |
+ | Here you may configure the connection options for every queue backend
+ | used by your application. An example configuration is provided for
+ | each backend supported by Laravel. You're also free to add more.
+ |
+ | Drivers: "sync", "database", "beanstalkd", "sqs", "redis",
+ | "deferred", "background", "failover", "null"
+ |
+ */
+
+ 'connections' => [
+
+ 'sync' => [
+ 'driver' => 'sync',
+ ],
+
+ 'database' => [
+ 'driver' => 'database',
+ 'connection' => env('DB_QUEUE_CONNECTION'),
+ 'table' => env('DB_QUEUE_TABLE', 'jobs'),
+ 'queue' => env('DB_QUEUE', 'default'),
+ 'retry_after' => (int) env('DB_QUEUE_RETRY_AFTER', 90),
+ 'after_commit' => false,
+ ],
+
+ 'beanstalkd' => [
+ 'driver' => 'beanstalkd',
+ 'host' => env('BEANSTALKD_QUEUE_HOST', 'localhost'),
+ 'queue' => env('BEANSTALKD_QUEUE', 'default'),
+ 'retry_after' => (int) env('BEANSTALKD_QUEUE_RETRY_AFTER', 90),
+ 'block_for' => 0,
+ 'after_commit' => false,
+ ],
+
+ 'sqs' => [
+ 'driver' => 'sqs',
+ 'key' => env('AWS_ACCESS_KEY_ID'),
+ 'secret' => env('AWS_SECRET_ACCESS_KEY'),
+ 'prefix' => env('SQS_PREFIX', 'https://sqs.us-east-1.amazonaws.com/your-account-id'),
+ 'queue' => env('SQS_QUEUE', 'default'),
+ 'suffix' => env('SQS_SUFFIX'),
+ 'region' => env('AWS_DEFAULT_REGION', 'us-east-1'),
+ 'after_commit' => false,
+ ],
+
+ 'redis' => [
+ 'driver' => 'redis',
+ 'connection' => env('REDIS_QUEUE_CONNECTION', 'default'),
+ 'queue' => env('REDIS_QUEUE', 'default'),
+ 'retry_after' => (int) env('REDIS_QUEUE_RETRY_AFTER', 90),
+ 'block_for' => null,
+ 'after_commit' => false,
+ ],
+
+ 'deferred' => [
+ 'driver' => 'deferred',
+ ],
+
+ 'background' => [
+ 'driver' => 'background',
+ ],
+
+ 'failover' => [
+ 'driver' => 'failover',
+ 'connections' => [
+ 'database',
+ 'deferred',
+ ],
+ ],
+
+ ],
+
+ /*
+ |--------------------------------------------------------------------------
+ | Job Batching
+ |--------------------------------------------------------------------------
+ |
+ | The following options configure the database and table that store job
+ | batching information. These options can be updated to any database
+ | connection and table which has been defined by your application.
+ |
+ */
+
+ 'batching' => [
+ 'database' => env('DB_CONNECTION', 'sqlite'),
+ 'table' => 'job_batches',
+ ],
+
+ /*
+ |--------------------------------------------------------------------------
+ | Failed Queue Jobs
+ |--------------------------------------------------------------------------
+ |
+ | These options configure the behavior of failed queue job logging so you
+ | can control how and where failed jobs are stored. Laravel ships with
+ | support for storing failed jobs in a simple file or in a database.
+ |
+ | Supported drivers: "database-uuids", "dynamodb", "file", "null"
+ |
+ */
+
+ 'failed' => [
+ 'driver' => env('QUEUE_FAILED_DRIVER', 'database-uuids'),
+ 'database' => env('DB_CONNECTION', 'sqlite'),
+ 'table' => 'failed_jobs',
+ ],
+
+];
diff --git a/config/sanctum.php b/config/sanctum.php
new file mode 100644
index 0000000..fe29637
--- /dev/null
+++ b/config/sanctum.php
@@ -0,0 +1,89 @@
+ explode(',', env('SANCTUM_STATEFUL_DOMAINS', sprintf(
+ '%s%s',
+ 'localhost,localhost:3000,127.0.0.1,127.0.0.1:8000,::1',
+ Sanctum::currentApplicationUrlWithPort(),
+ // Sanctum::currentRequestHost(),
+ ))),
+
+ /*
+ |--------------------------------------------------------------------------
+ | Sanctum Guards
+ |--------------------------------------------------------------------------
+ |
+ | This array contains the authentication guards that will be checked when
+ | Sanctum is trying to authenticate a request. If none of these guards
+ | are able to authenticate the request, Sanctum will use the bearer
+ | token that's present on an incoming request for authentication.
+ |
+ */
+
+ 'guard' => ['web'],
+
+ /*
+ |--------------------------------------------------------------------------
+ | Expiration Minutes
+ |--------------------------------------------------------------------------
+ |
+ | This value controls the number of minutes until an issued token will be
+ | considered expired. This will override any values set in the token's
+ | "expires_at" attribute, but first-party sessions are not affected.
+ |
+ */
+
+ 'expiration' => null,
+
+ /*
+ |--------------------------------------------------------------------------
+ | Token Prefix
+ |--------------------------------------------------------------------------
+ |
+ | Sanctum can prefix new tokens in order to take advantage of numerous
+ | security scanning initiatives maintained by open source platforms
+ | that notify developers if they commit tokens into repositories.
+ |
+ | See: https://docs.github.com/en/code-security/secret-scanning/about-secret-scanning
+ |
+ */
+
+ 'token_prefix' => env('SANCTUM_TOKEN_PREFIX', ''),
+
+ /*
+ |--------------------------------------------------------------------------
+ | Sanctum Middleware
+ |--------------------------------------------------------------------------
+ |
+ | When authenticating your first-party SPA with Sanctum you may need to
+ | customize some of the middleware Sanctum uses while processing the
+ | request. You may change the middleware listed below as required.
+ |
+ */
+
+ 'middleware' => [
+ 'authenticate_session' => AuthenticateSession::class,
+ 'encrypt_cookies' => EncryptCookies::class,
+ 'validate_csrf_token' => ValidateCsrfToken::class,
+ ],
+
+];
diff --git a/config/services.php b/config/services.php
new file mode 100644
index 0000000..583c3e1
--- /dev/null
+++ b/config/services.php
@@ -0,0 +1,40 @@
+ [
+ 'key' => env('POSTMARK_API_KEY'),
+ ],
+
+ 'resend' => [
+ 'key' => env('RESEND_API_KEY'),
+ ],
+
+ 'ses' => [
+ 'key' => env('AWS_ACCESS_KEY_ID'),
+ 'secret' => env('AWS_SECRET_ACCESS_KEY'),
+ 'region' => env('AWS_DEFAULT_REGION', 'us-east-1'),
+ ],
+
+ 'slack' => [
+ 'notifications' => [
+ 'bot_user_oauth_token' => env('SLACK_BOT_USER_OAUTH_TOKEN'),
+ 'channel' => env('SLACK_BOT_USER_DEFAULT_CHANNEL'),
+ ],
+ ],
+
+];
diff --git a/config/session.php b/config/session.php
new file mode 100644
index 0000000..e1dd549
--- /dev/null
+++ b/config/session.php
@@ -0,0 +1,235 @@
+ env('SESSION_DRIVER', 'database'),
+
+ /*
+ |--------------------------------------------------------------------------
+ | Session Lifetime
+ |--------------------------------------------------------------------------
+ |
+ | Here you may specify the number of minutes that you wish the session
+ | to be allowed to remain idle before it expires. If you want them
+ | to expire immediately when the browser is closed then you may
+ | indicate that via the expire_on_close configuration option.
+ |
+ */
+
+ 'lifetime' => (int) env('SESSION_LIFETIME', 120),
+
+ 'expire_on_close' => env('SESSION_EXPIRE_ON_CLOSE', false),
+
+ /*
+ |--------------------------------------------------------------------------
+ | Session Encryption
+ |--------------------------------------------------------------------------
+ |
+ | This option allows you to easily specify that all of your session data
+ | should be encrypted before it's stored. All encryption is performed
+ | automatically by Laravel and you may use the session like normal.
+ |
+ */
+
+ 'encrypt' => env('SESSION_ENCRYPT', false),
+
+ /*
+ |--------------------------------------------------------------------------
+ | Session File Location
+ |--------------------------------------------------------------------------
+ |
+ | When utilizing the "file" session driver, the session files are placed
+ | on disk. The default storage location is defined here; however, you
+ | are free to provide another location where they should be stored.
+ |
+ */
+
+ 'files' => storage_path('framework/sessions'),
+
+ /*
+ |--------------------------------------------------------------------------
+ | Session Database Connection
+ |--------------------------------------------------------------------------
+ |
+ | When using the "database" or "redis" session drivers, you may specify a
+ | connection that should be used to manage these sessions. This should
+ | correspond to a connection in your database configuration options.
+ |
+ */
+
+ 'connection' => env('SESSION_CONNECTION'),
+
+ /*
+ |--------------------------------------------------------------------------
+ | Session Database Table
+ |--------------------------------------------------------------------------
+ |
+ | When using the "database" session driver, you may specify the table to
+ | be used to store sessions. Of course, a sensible default is defined
+ | for you; however, you're welcome to change this to another table.
+ |
+ */
+
+ 'table' => env('SESSION_TABLE', 'sessions'),
+
+ /*
+ |--------------------------------------------------------------------------
+ | Session Cache Store
+ |--------------------------------------------------------------------------
+ |
+ | When using one of the framework's cache driven session backends, you may
+ | define the cache store which should be used to store the session data
+ | between requests. This must match one of your defined cache stores.
+ |
+ | Affects: "dynamodb", "memcached", "redis"
+ |
+ */
+
+ 'store' => env('SESSION_STORE'),
+
+ /*
+ |--------------------------------------------------------------------------
+ | Session Sweeping Lottery
+ |--------------------------------------------------------------------------
+ |
+ | Some session drivers must manually sweep their storage location to get
+ | rid of old sessions from storage. Here are the chances that it will
+ | happen on a given request. By default, the odds are 2 out of 100.
+ |
+ */
+
+ 'lottery' => [2, 100],
+
+ /*
+ |--------------------------------------------------------------------------
+ | Session Cookie Name
+ |--------------------------------------------------------------------------
+ |
+ | Here you may change the name of the session cookie that is created by
+ | the framework. Typically, you should not need to change this value
+ | since doing so does not grant a meaningful security improvement.
+ |
+ */
+
+ 'cookie' => env(
+ 'SESSION_COOKIE',
+ Str::slug((string) env('APP_NAME', 'laravel')) . '-session'
+ ),
+
+ /*
+ |--------------------------------------------------------------------------
+ | Session Cookie Path
+ |--------------------------------------------------------------------------
+ |
+ | The session cookie path determines the path for which the cookie will
+ | be regarded as available. Typically, this will be the root path of
+ | your application, but you're free to change this when necessary.
+ |
+ */
+
+ 'path' => env('SESSION_PATH', '/'),
+
+ /*
+ |--------------------------------------------------------------------------
+ | Session Cookie Domain
+ |--------------------------------------------------------------------------
+ |
+ | This value determines the domain and subdomains the session cookie is
+ | available to. By default, the cookie will be available to the root
+ | domain without subdomains. Typically, this shouldn't be changed.
+ |
+ */
+
+ 'domain' => env('SESSION_DOMAIN'),
+
+ /*
+ |--------------------------------------------------------------------------
+ | HTTPS Only Cookies
+ |--------------------------------------------------------------------------
+ |
+ | By setting this option to true, session cookies will only be sent back
+ | to the server if the browser has a HTTPS connection. This will keep
+ | the cookie from being sent to you when it can't be done securely.
+ |
+ */
+
+ 'secure' => env('SESSION_SECURE_COOKIE'),
+
+ /*
+ |--------------------------------------------------------------------------
+ | HTTP Access Only
+ |--------------------------------------------------------------------------
+ |
+ | Setting this value to true will prevent JavaScript from accessing the
+ | value of the cookie and the cookie will only be accessible through
+ | the HTTP protocol. It's unlikely you should disable this option.
+ |
+ */
+
+ 'http_only' => env('SESSION_HTTP_ONLY', true),
+
+ /*
+ |--------------------------------------------------------------------------
+ | Same-Site Cookies
+ |--------------------------------------------------------------------------
+ |
+ | This option determines how your cookies behave when cross-site requests
+ | take place, and can be used to mitigate CSRF attacks. By default, we
+ | will set this value to "lax" to permit secure cross-site requests.
+ |
+ | See: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie#samesitesamesite-value
+ |
+ | Supported: "lax", "strict", "none", null
+ |
+ */
+
+ 'same_site' => env('SESSION_SAME_SITE', 'lax'),
+
+ /*
+ |--------------------------------------------------------------------------
+ | Partitioned Cookies
+ |--------------------------------------------------------------------------
+ |
+ | Setting this value to true will tie the cookie to the top-level site for
+ | a cross-site context. Partitioned cookies are accepted by the browser
+ | when flagged "secure" and the Same-Site attribute is set to "none".
+ |
+ */
+
+ 'partitioned' => env('SESSION_PARTITIONED_COOKIE', false),
+
+ /*
+ |--------------------------------------------------------------------------
+ | Session Serialization
+ |--------------------------------------------------------------------------
+ |
+ | This value controls the serialization strategy for session data, which
+ | is JSON by default. Setting this to "php" allows the storage of PHP
+ | objects in the session but can make an application vulnerable to
+ | "gadget chain" serialization attacks if the APP_KEY is leaked.
+ |
+ | Supported: "json", "php"
+ |
+ */
+
+ 'serialization' => 'json',
+
+];
diff --git a/config/spectator.php b/config/spectator.php
new file mode 100644
index 0000000..57e90ed
--- /dev/null
+++ b/config/spectator.php
@@ -0,0 +1,83 @@
+ env('SPEC_SOURCE', 'local'),
+
+ /*
+ |--------------------------------------------------------------------------
+ | Sources
+ |--------------------------------------------------------------------------
+ |
+ | Here you may configure as many sources as you wish, and you
+ | may even configure multiple source of the same type. Defaults have
+ | been setup for each driver as an example of the required options.
+ |
+ */
+
+ 'sources' => [
+ 'local' => [
+ 'source' => 'local',
+ 'base_path' => env('SPEC_PATH'),
+ ],
+
+ 'remote' => [
+ 'source' => 'remote',
+ 'base_path' => env('SPEC_PATH'),
+ 'params' => env('SPEC_URL_PARAMS', ''),
+ ],
+
+ 'github' => [
+ 'source' => 'github',
+ 'base_path' => env('SPEC_GITHUB_PATH'),
+ 'repo' => env('SPEC_GITHUB_REPO'),
+ 'token' => env('SPEC_GITHUB_TOKEN'),
+ ],
+ ],
+
+ /*
+ |--------------------------------------------------------------------------
+ | Paths
+ |--------------------------------------------------------------------------
+ |
+ | Configure path defaults, like prefixes.
+ |
+ */
+
+ 'path_prefix' => 'api/v1',
+
+ /*
+ |--------------------------------------------------------------------------
+ | Error Format
+ |--------------------------------------------------------------------------
+ |
+ | Controls the format of schema validation error messages in test output.
+ | Use 'text' (default) for human-readable coloured terminal output, or
+ | 'json' for machine-readable output suited to CI log parsers and LLMs.
+ |
+ | You can also call Spectator::useJsonErrors() / useTextErrors() per-test.
+ |
+ */
+
+ 'error_format' => env('SPECTATOR_ERROR_FORMAT', 'text'),
+
+ /*
+ |--------------------------------------------------------------------------
+ |
+ | Specify the groups that spectator's middleware should be prepended to.
+ |
+ */
+
+ 'middleware_groups' => ['api'],
+];
diff --git a/config/view.php b/config/view.php
new file mode 100644
index 0000000..b6cdc70
--- /dev/null
+++ b/config/view.php
@@ -0,0 +1,38 @@
+ [
+ base_path('src/Presentation/Web/resources/views'),
+ ],
+
+ /*
+ |--------------------------------------------------------------------------
+ | Compiled View Path
+ |--------------------------------------------------------------------------
+ |
+ | This option determines where all the compiled Blade templates will be
+ | stored for your application. Typically, this is within the storage
+ | directory. However, as usual, you are free to change this value.
+ |
+ */
+
+ 'compiled' => env(
+ 'VIEW_COMPILED_PATH',
+ realpath(storage_path('framework/views'))
+ ),
+
+];
diff --git a/database/.gitignore b/database/.gitignore
new file mode 100644
index 0000000..9b19b93
--- /dev/null
+++ b/database/.gitignore
@@ -0,0 +1 @@
+*.sqlite*
diff --git a/database/factories/EmployeeFactory.php b/database/factories/EmployeeFactory.php
new file mode 100644
index 0000000..c29b27b
--- /dev/null
+++ b/database/factories/EmployeeFactory.php
@@ -0,0 +1,35 @@
+
+ */
+final class EmployeeFactory extends Factory
+{
+ protected $model = Employee::class;
+
+ /**
+ * @return array
+ */
+ #[\Override]
+ public function definition(): array
+ {
+ return [
+ 'public_employee_number' => (string) fake()->unique()->numberBetween(1000000, 9999999),
+ 'last_name' => strtoupper(fake()->lastName()),
+ 'first_name' => fake()->firstName(),
+ 'start_date' => '2024-01-15',
+ 'end_date' => null,
+ 'planned_end_date' => null,
+ 'establishment' => '01',
+ 'site' => 'LDCSER',
+ 'service' => '097',
+ ];
+ }
+}
diff --git a/database/factories/UserFactory.php b/database/factories/UserFactory.php
new file mode 100644
index 0000000..d2c4b35
--- /dev/null
+++ b/database/factories/UserFactory.php
@@ -0,0 +1,46 @@
+
+ */
+class UserFactory extends Factory
+{
+ /**
+ * The current password being used by the factory.
+ */
+ protected static ?string $password;
+
+ /**
+ * Define the model's default state.
+ *
+ * @return array
+ */
+ public function definition(): array
+ {
+ return [
+ 'name' => fake()->name(),
+ 'email' => fake()->unique()->safeEmail(),
+ 'email_verified_at' => now(),
+ 'password' => static::$password ??= Hash::make('password'),
+ 'remember_token' => Str::random(10),
+ ];
+ }
+
+ /**
+ * Indicate that the model's email address should be unverified.
+ */
+ public function unverified(): static
+ {
+ return $this->state(fn (array $attributes) => [
+ 'email_verified_at' => null,
+ ]);
+ }
+}
diff --git a/database/migrations/0001_01_01_000000_create_users_table.php b/database/migrations/0001_01_01_000000_create_users_table.php
new file mode 100644
index 0000000..622c352
--- /dev/null
+++ b/database/migrations/0001_01_01_000000_create_users_table.php
@@ -0,0 +1,51 @@
+id();
+ $table->string('name');
+ $table->string('email')->unique();
+ $table->timestamp('email_verified_at')->nullable();
+ $table->string('password');
+ $table->rememberToken();
+ $table->timestamps();
+ });
+
+ Schema::create('password_reset_tokens', function (Blueprint $table) {
+ $table->string('email')->primary();
+ $table->string('token');
+ $table->timestamp('created_at')->nullable();
+ });
+
+ Schema::create('sessions', function (Blueprint $table) {
+ $table->string('id')->primary();
+ $table->foreignId('user_id')->nullable()->index();
+ $table->string('ip_address', 45)->nullable();
+ $table->text('user_agent')->nullable();
+ $table->longText('payload');
+ $table->integer('last_activity')->index();
+ });
+ }
+
+ /**
+ * Reverse the migrations.
+ */
+ public function down(): void
+ {
+ Schema::dropIfExists('users');
+ Schema::dropIfExists('password_reset_tokens');
+ Schema::dropIfExists('sessions');
+ }
+};
diff --git a/database/migrations/0001_01_01_000001_create_cache_table.php b/database/migrations/0001_01_01_000001_create_cache_table.php
new file mode 100644
index 0000000..6af2b23
--- /dev/null
+++ b/database/migrations/0001_01_01_000001_create_cache_table.php
@@ -0,0 +1,37 @@
+string('key')->primary();
+ $table->mediumText('value');
+ $table->bigInteger('expiration')->index();
+ });
+
+ Schema::create('cache_locks', function (Blueprint $table) {
+ $table->string('key')->primary();
+ $table->string('owner');
+ $table->bigInteger('expiration')->index();
+ });
+ }
+
+ /**
+ * Reverse the migrations.
+ */
+ public function down(): void
+ {
+ Schema::dropIfExists('cache');
+ Schema::dropIfExists('cache_locks');
+ }
+};
diff --git a/database/migrations/0001_01_01_000002_create_jobs_table.php b/database/migrations/0001_01_01_000002_create_jobs_table.php
new file mode 100644
index 0000000..64410da
--- /dev/null
+++ b/database/migrations/0001_01_01_000002_create_jobs_table.php
@@ -0,0 +1,61 @@
+id();
+ $table->string('queue')->index();
+ $table->longText('payload');
+ $table->unsignedSmallInteger('attempts');
+ $table->unsignedInteger('reserved_at')->nullable();
+ $table->unsignedInteger('available_at');
+ $table->unsignedInteger('created_at');
+ });
+
+ Schema::create('job_batches', function (Blueprint $table) {
+ $table->string('id')->primary();
+ $table->string('name');
+ $table->integer('total_jobs');
+ $table->integer('pending_jobs');
+ $table->integer('failed_jobs');
+ $table->longText('failed_job_ids');
+ $table->mediumText('options')->nullable();
+ $table->integer('cancelled_at')->nullable();
+ $table->integer('created_at');
+ $table->integer('finished_at')->nullable();
+ });
+
+ Schema::create('failed_jobs', function (Blueprint $table) {
+ $table->id();
+ $table->string('uuid')->unique();
+ $table->string('connection');
+ $table->string('queue');
+ $table->longText('payload');
+ $table->longText('exception');
+ $table->timestamp('failed_at')->useCurrent();
+
+ $table->index(['connection', 'queue', 'failed_at']);
+ });
+ }
+
+ /**
+ * Reverse the migrations.
+ */
+ public function down(): void
+ {
+ Schema::dropIfExists('jobs');
+ Schema::dropIfExists('job_batches');
+ Schema::dropIfExists('failed_jobs');
+ }
+};
diff --git a/database/migrations/2026_08_10_145239_create_personal_access_tokens_table.php b/database/migrations/2026_08_10_145239_create_personal_access_tokens_table.php
new file mode 100644
index 0000000..b4842f8
--- /dev/null
+++ b/database/migrations/2026_08_10_145239_create_personal_access_tokens_table.php
@@ -0,0 +1,35 @@
+id();
+ $table->morphs('tokenable');
+ $table->text('name');
+ $table->string('token', 64)->unique();
+ $table->text('abilities')->nullable();
+ $table->timestamp('last_used_at')->nullable();
+ $table->timestamp('expires_at')->nullable()->index();
+ $table->timestamps();
+ });
+ }
+
+ /**
+ * Reverse the migrations.
+ */
+ public function down(): void
+ {
+ Schema::dropIfExists('personal_access_tokens');
+ }
+};
diff --git a/database/migrations/2026_08_10_145347_create_api_clients_table.php b/database/migrations/2026_08_10_145347_create_api_clients_table.php
new file mode 100644
index 0000000..fe0d6a1
--- /dev/null
+++ b/database/migrations/2026_08_10_145347_create_api_clients_table.php
@@ -0,0 +1,35 @@
+uuid('id')->primary();
+
+ $table->string('name');
+ $table->string('identifier')->unique();
+ $table->string('secret');
+ $table->boolean('is_active');
+
+ $table->timestamps();
+ });
+ }
+
+ /**
+ * Reverse the migrations.
+ */
+ public function down(): void
+ {
+ Schema::dropIfExists('api_clients');
+ }
+};
diff --git a/database/migrations/2026_08_11_000000_create_employees_table.php b/database/migrations/2026_08_11_000000_create_employees_table.php
new file mode 100644
index 0000000..e4233ed
--- /dev/null
+++ b/database/migrations/2026_08_11_000000_create_employees_table.php
@@ -0,0 +1,47 @@
+dropIfExists('employees');
+
+ $schema->create('employees', function (Blueprint $table) {
+ $table->string('public_employee_number', 8)->primary();
+ $table->string('last_name');
+ $table->string('first_name');
+ $table->date('start_date');
+ $table->date('end_date')->nullable();
+ $table->date('planned_end_date')->nullable();
+ $table->string('establishment', 20);
+ $table->string('site', 20);
+ $table->string('service', 20);
+ $table->timestamps();
+
+ $table->index('site');
+ $table->index('service');
+ $table->index('establishment');
+ });
+ }
+
+ /**
+ * Reverse the migrations.
+ */
+ public function down(): void
+ {
+ Schema::connection(Config::string('database.arcadia_meta_model'))
+ ->dropIfExists('employees');
+ }
+};
diff --git a/database/seeders/DatabaseSeeder.php b/database/seeders/DatabaseSeeder.php
new file mode 100644
index 0000000..a7bdace
--- /dev/null
+++ b/database/seeders/DatabaseSeeder.php
@@ -0,0 +1,21 @@
+call(EmployeeSeeder::class);
+ }
+}
diff --git a/database/seeders/EmployeeSeeder.php b/database/seeders/EmployeeSeeder.php
new file mode 100644
index 0000000..fff68b4
--- /dev/null
+++ b/database/seeders/EmployeeSeeder.php
@@ -0,0 +1,84 @@
+upsert([
+ [
+ 'public_employee_number' => '01155902',
+ 'last_name' => 'DOE',
+ 'first_name' => 'John',
+ 'start_date' => '2024-01-15',
+ 'end_date' => null,
+ 'planned_end_date' => null,
+ 'establishment' => '01',
+ 'site' => 'LDCSER',
+ 'service' => '097',
+ 'created_at' => $timestamp,
+ 'updated_at' => $timestamp,
+ ],
+ [
+ 'public_employee_number' => '1234567',
+ 'last_name' => 'MARTIN',
+ 'first_name' => 'Alice',
+ 'start_date' => '2024-01-08',
+ 'end_date' => null,
+ 'planned_end_date' => null,
+ 'establishment' => 'LY',
+ 'site' => 'LDCSER',
+ 'service' => '101',
+ 'created_at' => $timestamp,
+ 'updated_at' => $timestamp,
+ ],
+ [
+ 'public_employee_number' => '2345678',
+ 'last_name' => 'DUPONT',
+ 'first_name' => 'Louis',
+ 'start_date' => '2023-05-15',
+ 'end_date' => null,
+ 'planned_end_date' => '2026-12-31',
+ 'establishment' => 'PA',
+ 'site' => 'SLELA',
+ 'service' => '097',
+ 'created_at' => $timestamp,
+ 'updated_at' => $timestamp,
+ ],
+ [
+ 'public_employee_number' => '3456789',
+ 'last_name' => 'BERNARD',
+ 'first_name' => 'Nora',
+ 'start_date' => '2022-09-01',
+ 'end_date' => null,
+ 'planned_end_date' => null,
+ 'establishment' => 'BO',
+ 'site' => 'DDE',
+ 'service' => '205',
+ 'created_at' => $timestamp,
+ 'updated_at' => $timestamp,
+ ],
+ ], ['public_employee_number'], [
+ 'last_name',
+ 'first_name',
+ 'start_date',
+ 'end_date',
+ 'planned_end_date',
+ 'establishment',
+ 'site',
+ 'service',
+ 'updated_at',
+ ]);
+ }
+}
diff --git a/documentation/Bruno/Arcadia Api/.gitignore b/documentation/Bruno/Arcadia Api/.gitignore
new file mode 100644
index 0000000..e19311f
--- /dev/null
+++ b/documentation/Bruno/Arcadia Api/.gitignore
@@ -0,0 +1,9 @@
+# Secrets
+.env*
+
+# Dependencies
+node_modules
+
+# OS files
+.DS_Store
+Thumbs.db
\ No newline at end of file
diff --git a/documentation/Bruno/Arcadia Api/Api/Api Root.yml b/documentation/Bruno/Arcadia Api/Api/Api Root.yml
new file mode 100644
index 0000000..d8c8dc4
--- /dev/null
+++ b/documentation/Bruno/Arcadia Api/Api/Api Root.yml
@@ -0,0 +1,15 @@
+info:
+ name: Api Root
+ type: http
+ seq: 2
+
+http:
+ method: GET
+ url: "{{ENDPOINT}}/api/"
+ auth: inherit
+
+settings:
+ encodeUrl: true
+ timeout: 0
+ followRedirects: true
+ maxRedirects: 5
diff --git a/documentation/Bruno/Arcadia Api/Api/V1/Employees/Get Employee.yml b/documentation/Bruno/Arcadia Api/Api/V1/Employees/Get Employee.yml
new file mode 100644
index 0000000..3acda59
--- /dev/null
+++ b/documentation/Bruno/Arcadia Api/Api/V1/Employees/Get Employee.yml
@@ -0,0 +1,19 @@
+info:
+ name: Get Employee
+ type: http
+ seq: 2
+
+http:
+ method: GET
+ url: "{{ENDPOINT}}/api/{{APIV1}}/employees/:employeeId"
+ params:
+ - name: employeeId
+ value: "{{EMPLOYEE_ID}}"
+ type: path
+ auth: inherit
+
+settings:
+ encodeUrl: true
+ timeout: 0
+ followRedirects: true
+ maxRedirects: 5
diff --git a/documentation/Bruno/Arcadia Api/Api/V1/Employees/List Employees.yml b/documentation/Bruno/Arcadia Api/Api/V1/Employees/List Employees.yml
new file mode 100644
index 0000000..35a7b46
--- /dev/null
+++ b/documentation/Bruno/Arcadia Api/Api/V1/Employees/List Employees.yml
@@ -0,0 +1,62 @@
+info:
+ name: List Employees
+ type: http
+ seq: 1
+
+http:
+ method: GET
+ url: "{{ENDPOINT}}/api/{{APIV1}}/employees?page=1&pageSize=25&sortBy=arcadiaId&sortDirection=Ascending"
+ params:
+ - name: page
+ value: "1"
+ type: query
+ description: 1-based page index
+ - name: pageSize
+ value: "25"
+ type: query
+ description: Number of items per page (max 10000)
+ - name: offset
+ value: "0"
+ type: query
+ description: Offset for offset-based pagination
+ disabled: true
+ - name: limit
+ value: "25"
+ type: query
+ description: Limit for offset-based pagination
+ disabled: true
+ - name: since
+ value: 2026-01-01T00:00:00Z
+ type: query
+ description: Filter employees updated since timestamp (RFC3339)
+ disabled: true
+ - name: establishment
+ value: "01"
+ type: query
+ description: Filter by establishment code (e.g. 01, PA, LY)
+ disabled: true
+ - name: siteId
+ value: LDCSER
+ type: query
+ description: Filter by site ID (e.g. LDCSER, SLELA)
+ disabled: true
+ - name: serviceId
+ value: "097"
+ type: query
+ description: Filter by service ID (e.g. 097, 101)
+ disabled: true
+ - name: sortBy
+ value: arcadiaId
+ type: query
+ description: "Sort column: arcadiaId, startDate, endDate, plannedEndDate, createdAt, updatedAt"
+ - name: sortDirection
+ value: Ascending
+ type: query
+ description: "Sort direction: Ascending or Descending"
+ auth: inherit
+
+settings:
+ encodeUrl: true
+ timeout: 0
+ followRedirects: true
+ maxRedirects: 5
diff --git a/documentation/Bruno/Arcadia Api/Api/V1/Employees/folder.yml b/documentation/Bruno/Arcadia Api/Api/V1/Employees/folder.yml
new file mode 100644
index 0000000..607daed
--- /dev/null
+++ b/documentation/Bruno/Arcadia Api/Api/V1/Employees/folder.yml
@@ -0,0 +1,7 @@
+info:
+ name: Employees
+ type: folder
+ seq: 3
+
+request:
+ auth: inherit
diff --git a/documentation/Bruno/Arcadia Api/Api/V1/OpenApi Spec.yml b/documentation/Bruno/Arcadia Api/Api/V1/OpenApi Spec.yml
new file mode 100644
index 0000000..3f8aec2
--- /dev/null
+++ b/documentation/Bruno/Arcadia Api/Api/V1/OpenApi Spec.yml
@@ -0,0 +1,15 @@
+info:
+ name: OpenApi Spec
+ type: http
+ seq: 3
+
+http:
+ method: GET
+ url: "{{ENDPOINT}}/api/{{APIV1}}/openapi"
+ auth: inherit
+
+settings:
+ encodeUrl: true
+ timeout: 0
+ followRedirects: true
+ maxRedirects: 5
diff --git a/documentation/Bruno/Arcadia Api/Api/V1/Ping.yml b/documentation/Bruno/Arcadia Api/Api/V1/Ping.yml
new file mode 100644
index 0000000..4a54d10
--- /dev/null
+++ b/documentation/Bruno/Arcadia Api/Api/V1/Ping.yml
@@ -0,0 +1,15 @@
+info:
+ name: Ping
+ type: http
+ seq: 2
+
+http:
+ method: GET
+ url: "{{ENDPOINT}}/api/{{APIV1}}/ping"
+ auth: inherit
+
+settings:
+ encodeUrl: true
+ timeout: 0
+ followRedirects: true
+ maxRedirects: 5
diff --git a/documentation/Bruno/Arcadia Api/Api/V1/Root.yml b/documentation/Bruno/Arcadia Api/Api/V1/Root.yml
new file mode 100644
index 0000000..ab17485
--- /dev/null
+++ b/documentation/Bruno/Arcadia Api/Api/V1/Root.yml
@@ -0,0 +1,15 @@
+info:
+ name: Root
+ type: http
+ seq: 1
+
+http:
+ method: GET
+ url: "{{ENDPOINT}}/api/{{APIV1}}/"
+ auth: inherit
+
+settings:
+ encodeUrl: true
+ timeout: 0
+ followRedirects: true
+ maxRedirects: 5
diff --git a/documentation/Bruno/Arcadia Api/Api/V1/folder.yml b/documentation/Bruno/Arcadia Api/Api/V1/folder.yml
new file mode 100644
index 0000000..2145466
--- /dev/null
+++ b/documentation/Bruno/Arcadia Api/Api/V1/folder.yml
@@ -0,0 +1,7 @@
+info:
+ name: V1
+ type: folder
+ seq: 2
+
+request:
+ auth: inherit
diff --git a/documentation/Bruno/Arcadia Api/Api/folder.yml b/documentation/Bruno/Arcadia Api/Api/folder.yml
new file mode 100644
index 0000000..682448d
--- /dev/null
+++ b/documentation/Bruno/Arcadia Api/Api/folder.yml
@@ -0,0 +1,7 @@
+info:
+ name: Api
+ type: folder
+ seq: 2
+
+request:
+ auth: inherit
diff --git a/documentation/Bruno/Arcadia Api/Root Url.yml b/documentation/Bruno/Arcadia Api/Root Url.yml
new file mode 100644
index 0000000..131300e
--- /dev/null
+++ b/documentation/Bruno/Arcadia Api/Root Url.yml
@@ -0,0 +1,15 @@
+info:
+ name: Root Url
+ type: http
+ seq: 1
+
+http:
+ method: GET
+ url: "{{ENDPOINT}}/"
+ auth: inherit
+
+settings:
+ encodeUrl: true
+ timeout: 0
+ followRedirects: true
+ maxRedirects: 5
diff --git a/documentation/Bruno/Arcadia Api/environments/Local Dev.yml b/documentation/Bruno/Arcadia Api/environments/Local Dev.yml
new file mode 100644
index 0000000..3c5d6ce
--- /dev/null
+++ b/documentation/Bruno/Arcadia Api/environments/Local Dev.yml
@@ -0,0 +1,11 @@
+name: Local Dev
+variables:
+ - name: ENDPOINT
+ value: http://127.0.0.1:8000
+ description: ""
+ - name: APIV1
+ value: v1
+ description: ""
+ - name: EMPLOYEE_ID
+ value: "01155902"
+ description: "Employee public matricule (7-8 digits)"
diff --git a/documentation/Bruno/Arcadia Api/opencollection.yml b/documentation/Bruno/Arcadia Api/opencollection.yml
new file mode 100644
index 0000000..3382001
--- /dev/null
+++ b/documentation/Bruno/Arcadia Api/opencollection.yml
@@ -0,0 +1,10 @@
+opencollection: 1.0.0
+
+info:
+ name: Arcadia Api
+bundled: false
+extensions:
+ bruno:
+ ignore:
+ - node_modules
+ - .git
diff --git a/documentation/OpenApi/openapi.yaml b/documentation/OpenApi/openapi.yaml
new file mode 100644
index 0000000..0781571
--- /dev/null
+++ b/documentation/OpenApi/openapi.yaml
@@ -0,0 +1,546 @@
+openapi: 3.1.0
+info:
+ title: Arcadia API
+ description: |
+ Arcadia API in order to abstract corporate metamodel to a proper and stable implemented API.
+ Architecture Clean Architecture, Domain-Driven Design (DDD) & Ports & Adapters (Hexagonale).
+ contact:
+ name: Uwil Engineering Team
+ email: digital@ldc.fr
+ license:
+ name: MIT
+ url: https://opensource.org/licenses/MIT
+ version: 1.0.0
+
+servers:
+ - url: http://127.0.0.1:8000/api/v1
+ description: Serveur de développement local v1
+
+security:
+ - HmacClientId: []
+ HmacTimestamp: []
+ HmacSignature: []
+
+tags:
+ - name: Employees
+ description: Gestion et consultation du référentiel RH des employés.
+
+paths:
+ /employees:
+ get:
+ tags:
+ - Employees
+ summary: Liste paginée des employés
+ description: |
+ Retourne la liste paginée des employés du système Arcadia.
+ Prend en charge le filtrage par date de modification (`since`), code établissement (`establishment`),
+ code site (`siteId`), code service (`serviceId`), ainsi que le tri et la pagination HATEOAS.
+ operationId: listEmployees
+ parameters:
+ - $ref: '#/components/parameters/Page'
+ - $ref: '#/components/parameters/PageSize'
+ - $ref: '#/components/parameters/Offset'
+ - $ref: '#/components/parameters/Limit'
+ - $ref: '#/components/parameters/Since'
+ - $ref: '#/components/parameters/Establishment'
+ - $ref: '#/components/parameters/SiteId'
+ - $ref: '#/components/parameters/ServiceId'
+ - $ref: '#/components/parameters/SortBy'
+ - $ref: '#/components/parameters/SortDirection'
+ responses:
+ '200':
+ description: Page d'employés récupérée avec succès.
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/EmployeeListResponse'
+ '400':
+ $ref: '#/components/responses/BadRequest'
+ '401':
+ $ref: '#/components/responses/Unauthorized'
+ '403':
+ $ref: '#/components/responses/Forbidden'
+ '422':
+ $ref: '#/components/responses/UnprocessableEntity'
+ '500':
+ $ref: '#/components/responses/InternalServerError'
+ '503':
+ $ref: '#/components/responses/ServiceUnavailable'
+
+ /employees/{employeeId}:
+ get:
+ tags:
+ - Employees
+ summary: Détail d'un employé par son identifiant
+ description: |
+ Retourne la fiche détaillée d'un employé spécifié par son matricule public unique.
+ operationId: getEmployee
+ parameters:
+ - $ref: '#/components/parameters/EmployeeIdPath'
+ responses:
+ '200':
+ description: Fiche employé trouvée.
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/EmployeeItemResponse'
+ '400':
+ $ref: '#/components/responses/BadRequest'
+ '401':
+ $ref: '#/components/responses/Unauthorized'
+ '403':
+ $ref: '#/components/responses/Forbidden'
+ '404':
+ $ref: '#/components/responses/NotFound'
+ '422':
+ $ref: '#/components/responses/UnprocessableEntity'
+ '500':
+ $ref: '#/components/responses/InternalServerError'
+ '503':
+ $ref: '#/components/responses/ServiceUnavailable'
+
+components:
+ securitySchemes:
+ HmacClientId:
+ type: apiKey
+ in: header
+ name: X-Client-Id
+ description: Identifiant public du client API autorisé.
+ HmacTimestamp:
+ type: apiKey
+ in: header
+ name: X-Timestamp
+ description: Horodatage au format ISO8601 / RFC3339 (tolérance anti-replay ±5 minutes).
+ HmacSignature:
+ type: apiKey
+ in: header
+ name: X-Signature
+ description: Signature HMAC-SHA256 calculée avec la clé secrète partagée.
+
+ parameters:
+ EmployeeIdPath:
+ name: employeeId
+ in: path
+ required: true
+ description: Matricule public unique de l'employé (7 ou 8 chiffres).
+ schema:
+ type: string
+ pattern: '^\d{7,8}$'
+ example: '01155902'
+
+ Page:
+ name: page
+ in: query
+ required: false
+ description: Numéro de page (1-based).
+ schema:
+ type: integer
+ minimum: 1
+ default: 1
+ example: 1
+
+ PageSize:
+ name: pageSize
+ in: query
+ required: false
+ description: Nombre d'éléments par page (max 10000).
+ schema:
+ type: integer
+ minimum: 1
+ maximum: 10000
+ default: 25
+ example: 25
+
+ Offset:
+ name: offset
+ in: query
+ required: false
+ description: Décalage d'index pour la pagination basée sur l'offset.
+ schema:
+ type: integer
+ minimum: 0
+ example: 0
+
+ Limit:
+ name: limit
+ in: query
+ required: false
+ description: Nombre maximal d'enregistrements pour la pagination par offset.
+ schema:
+ type: integer
+ minimum: 1
+ maximum: 10000
+ example: 25
+
+ Since:
+ name: since
+ in: query
+ required: false
+ description: Horodatage au format RFC3339 (borne inférieure sur updatedAt).
+ schema:
+ type: string
+ format: date-time
+ example: '2026-01-01T00:00:00Z'
+
+ Establishment:
+ name: establishment
+ in: query
+ required: false
+ description: "Filtrer par code établissement (ex: 01, PA, LY)."
+ schema:
+ type: string
+ pattern: '^[\dA-Z]{2,}$'
+ example: '01'
+
+ SiteId:
+ name: siteId
+ in: query
+ required: false
+ description: "Filtrer par code site (ex: LDCSER, SLELA)."
+ schema:
+ type: string
+ pattern: '^[A-Z]{2,}$'
+ example: 'LDCSER'
+
+ ServiceId:
+ name: serviceId
+ in: query
+ required: false
+ description: "Filtrer par identifiant de service (ex: 097, 101)."
+ schema:
+ type: string
+ pattern: '^\d{1,}$'
+ example: '097'
+
+ SortBy:
+ name: sortBy
+ in: query
+ required: false
+ description: Champ d'ordonnancement des employés.
+ schema:
+ type: string
+ enum:
+ - arcadiaId
+ - startDate
+ - endDate
+ - plannedEndDate
+ - createdAt
+ - updatedAt
+ default: arcadiaId
+ example: arcadiaId
+
+ SortDirection:
+ name: sortDirection
+ in: query
+ required: false
+ description: Sens du tri.
+ schema:
+ type: string
+ enum:
+ - Ascending
+ - Descending
+ default: Ascending
+ example: Ascending
+
+ responses:
+ BadRequest:
+ description: Requête malformée ou paramètres invalides (400 Bad Request).
+ content:
+ application/problem+json:
+ schema:
+ $ref: '#/components/schemas/ProblemDetails'
+
+ Unauthorized:
+ description: Échec d'authentification HMAC ou signature invalide (401 Unauthorized).
+ content:
+ application/problem+json:
+ schema:
+ $ref: '#/components/schemas/ProblemDetails'
+
+ Forbidden:
+ description: Client non autorisé à accéder à cette ressource (403 Forbidden).
+ content:
+ application/problem+json:
+ schema:
+ $ref: '#/components/schemas/ProblemDetails'
+
+ NotFound:
+ description: Ressource introuvable (404 Not Found).
+ content:
+ application/problem+json:
+ schema:
+ $ref: '#/components/schemas/ProblemDetails'
+
+ UnprocessableEntity:
+ description: Erreurs de validation de la requête HTTP (422 Unprocessable Entity).
+ content:
+ application/problem+json:
+ schema:
+ $ref: '#/components/schemas/ValidationErrorProblemDetails'
+
+ InternalServerError:
+ description: Erreur interne du serveur (500 Internal Server Error).
+ content:
+ application/problem+json:
+ schema:
+ $ref: '#/components/schemas/ProblemDetails'
+
+ ServiceUnavailable:
+ description: Service temporairement indisponible (503 Service Unavailable).
+ content:
+ application/problem+json:
+ schema:
+ $ref: '#/components/schemas/ProblemDetails'
+
+ schemas:
+ Employee:
+ type: object
+ description: Représentation canonique d'un employé dans le métamodèle Arcadia.
+ required:
+ - id
+ - firstName
+ - lastName
+ - establishment
+ - site
+ - service
+ - startDate
+ properties:
+ id:
+ type: string
+ pattern: '^\d{7,8}$'
+ description: Matricule public unique de l'employé.
+ example: '01155902'
+ firstName:
+ type: string
+ description: Prénom de l'employé.
+ example: John
+ lastName:
+ type: string
+ description: Nom de famille de l'employé.
+ example: DOE
+ establishment:
+ type: string
+ pattern: '^[\dA-Z]{2,}$'
+ description: Code de l'établissement d'affectation.
+ example: '01'
+ site:
+ type: string
+ pattern: '^[A-Z]{2,}$'
+ description: Code du site géographique.
+ example: LDCSER
+ service:
+ type: string
+ pattern: '^\d{1,}$'
+ description: Identifiant du service interne.
+ example: '097'
+ startDate:
+ type: string
+ format: date
+ description: Date de prise de poste (YYYY-MM-DD).
+ example: '2024-01-15'
+ endDate:
+ type:
+ - string
+ - 'null'
+ format: date
+ description: Date de fin de contrat effective (optionnelle).
+ example: null
+ plannedEndDate:
+ type:
+ - string
+ - 'null'
+ format: date
+ description: Date de fin de contrat prévue (optionnelle).
+ example: null
+ createdAt:
+ type:
+ - string
+ - 'null'
+ format: date-time
+ description: Date d'enregistrement dans le système.
+ example: '2026-08-11T14:00:00Z'
+ updatedAt:
+ type:
+ - string
+ - 'null'
+ format: date-time
+ description: Date de dernière mise à jour.
+ example: '2026-08-11T14:00:00Z'
+
+ PaginationLinks:
+ type: object
+ description: Liens de navigation HATEOAS pour la pagination.
+ required:
+ - self
+ - first
+ - last
+ properties:
+ self:
+ type: string
+ format: uri
+ description: Lien vers la page courante.
+ example: 'http://127.0.0.1:8000/api/v1/employees?page=1&pageSize=25'
+ first:
+ type: string
+ format: uri
+ description: Lien vers la première page.
+ example: 'http://127.0.0.1:8000/api/v1/employees?page=1&pageSize=25'
+ prev:
+ type:
+ - string
+ - 'null'
+ format: uri
+ description: Lien vers la page précédente (null si première page).
+ example: null
+ next:
+ type:
+ - string
+ - 'null'
+ format: uri
+ description: Lien vers la page suivante (null si dernière page).
+ example: 'http://127.0.0.1:8000/api/v1/employees?page=2&pageSize=25'
+ last:
+ type: string
+ format: uri
+ description: Lien vers la dernière page.
+ example: 'http://127.0.0.1:8000/api/v1/employees?page=2&pageSize=25'
+
+ PaginationMeta:
+ type: object
+ description: Métadonnées de pagination.
+ required:
+ - page
+ - pageSize
+ - totalItems
+ - totalPages
+ - links
+ properties:
+ page:
+ type: integer
+ minimum: 1
+ description: Index de la page courante (1-based).
+ example: 1
+ pageSize:
+ type: integer
+ minimum: 1
+ description: Nombre d'éléments par page.
+ example: 25
+ totalItems:
+ type: integer
+ minimum: 0
+ description: Nombre total d'éléments correspondant aux filtres.
+ example: 42
+ totalPages:
+ type: integer
+ minimum: 0
+ description: Nombre total de pages disponibles.
+ example: 2
+ links:
+ $ref: '#/components/schemas/PaginationLinks'
+
+ EmployeeListResponse:
+ type: object
+ description: Enveloppe de réponse pour la liste paginée des employés.
+ required:
+ - employees
+ - pagination
+ properties:
+ employees:
+ type: array
+ description: Collection des employés de la page.
+ items:
+ $ref: '#/components/schemas/Employee'
+ pagination:
+ $ref: '#/components/schemas/PaginationMeta'
+
+ EmployeeItemResponse:
+ type: object
+ description: Enveloppe de réponse pour le détail d'un employé.
+ required:
+ - employee
+ properties:
+ employee:
+ $ref: '#/components/schemas/Employee'
+
+ ProblemDetails:
+ type: object
+ description: Format d'erreur standardisé RFC 7807 (Problem Details for HTTP APIs).
+ required:
+ - type
+ - title
+ - status
+ - detail
+ properties:
+ type:
+ type: string
+ format: uri
+ description: URI identifiant le type de problème.
+ example: 'http://127.0.0.1:8000/errors/not-found'
+ title:
+ type: string
+ description: Titre court lisible résumant le problème.
+ example: 'Resource Not Found'
+ status:
+ type: integer
+ description: Code statut HTTP.
+ example: 404
+ detail:
+ type: string
+ description: Explication humaine détaillée de l'erreur.
+ example: "Employee '9999999' not found."
+ instance:
+ type:
+ - string
+ - 'null'
+ format: uri-reference
+ description: URI de l'endpoint ayant généré l'erreur.
+ example: '/api/v1/employees/9999999'
+
+ InvalidParamItem:
+ type: object
+ description: Détail d'une erreur de validation sur un paramètre.
+ required:
+ - name
+ - reason
+ properties:
+ name:
+ type: string
+ description: Nom du champ ou paramètre invalide.
+ example: employeeId
+ reason:
+ type: string
+ description: Raison du rejet de validation.
+ example: 'The employeeId pattern must be 7 or 8 digits.'
+
+ ValidationErrorProblemDetails:
+ type: object
+ description: Format RFC 7807 pour les erreurs de validation HTTP (422 Unprocessable Entity).
+ required:
+ - type
+ - title
+ - status
+ - detail
+ - invalidParams
+ properties:
+ type:
+ type: string
+ format: uri
+ description: URI identifiant l'erreur de validation.
+ example: 'http://127.0.0.1:8000/errors/validation-error'
+ title:
+ type: string
+ description: Titre de l'erreur.
+ example: 'Unprocessable Entity'
+ status:
+ type: integer
+ description: Code HTTP (422).
+ example: 422
+ detail:
+ type: string
+ description: Message d'ensemble.
+ example: 'The given data was invalid.'
+ invalidParams:
+ type: array
+ description: Liste des paramètres invalides et motifs.
+ items:
+ $ref: '#/components/schemas/InvalidParamItem'
diff --git a/documentation/OpenApi/original-endpoint.yaml b/documentation/OpenApi/original-endpoint.yaml
new file mode 100644
index 0000000..17fa001
--- /dev/null
+++ b/documentation/OpenApi/original-endpoint.yaml
@@ -0,0 +1,819 @@
+openapi: 3.1.1
+info:
+ title: Arcadia Genesis API (for PHP client)
+ version: 1.0.0
+ summary: Proposed HTTP API contract consumed by arcadia-genesis-php-client
+ description: |
+ This specification describes the API surface implied by the PHP client.
+ It models employee and INCO sheet use cases exposed by the client services.
+
+servers:
+ - url: https://api.example.com/gaston/api
+ description: Example production server
+
+security:
+ - ArcadiaAuth: []
+
+tags:
+ - name: Employees
+ - name: IncoSheets
+ - name: IncoComposition
+
+paths:
+ /employees:
+ get:
+ tags: [Employees]
+ operationId: listEmployees
+ summary: List employees
+ description: |
+ Returns a paginated list of employees.
+ Supports optional filtering by update timestamp and site ids.
+ parameters:
+ - $ref: '#/components/parameters/Page'
+ - $ref: '#/components/parameters/PageSize'
+ - $ref: '#/components/parameters/Since'
+ - $ref: '#/components/parameters/EmployeeSortBy'
+ - $ref: '#/components/parameters/SortDirection'
+ - name: siteIds
+ in: query
+ required: false
+ description: Filter on one or many site ids
+ style: form
+ explode: true
+ schema:
+ type: array
+ minItems: 1
+ items:
+ type: string
+ responses:
+ '200':
+ description: Employees page
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/EmployeeListResponse'
+ '400':
+ $ref: '#/components/responses/BadRequest'
+ '401':
+ $ref: '#/components/responses/Unauthorized'
+ '429':
+ $ref: '#/components/responses/TooManyRequests'
+ '503':
+ $ref: '#/components/responses/ServiceUnavailable'
+
+ /employees/{employeeId}:
+ get:
+ tags: [Employees]
+ operationId: getEmployeeById
+ summary: Get an employee by id
+ parameters:
+ - name: employeeId
+ in: path
+ required: true
+ schema:
+ type: string
+ responses:
+ '200':
+ description: Employee detail
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/EmployeeItemResponse'
+ '400':
+ $ref: '#/components/responses/BadRequest'
+ '401':
+ $ref: '#/components/responses/Unauthorized'
+ '404':
+ description: Employee not found
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/NotFoundResponse'
+ '429':
+ $ref: '#/components/responses/TooManyRequests'
+ '503':
+ $ref: '#/components/responses/ServiceUnavailable'
+
+ /inco-sheets:
+ get:
+ tags: [IncoSheets]
+ operationId: listIncoSheets
+ summary: List INCO sheets
+ description: |
+ Returns paginated INCO sheets.
+ Supports brand filtering and optional updated_at lower bound.
+ parameters:
+ - $ref: '#/components/parameters/Page'
+ - $ref: '#/components/parameters/PageSize'
+ - $ref: '#/components/parameters/Since'
+ - $ref: '#/components/parameters/IncoSortBy'
+ - $ref: '#/components/parameters/SortDirection'
+ - name: brands
+ in: query
+ required: false
+ description: Filter on one or many brand codes
+ style: form
+ explode: true
+ schema:
+ type: array
+ minItems: 1
+ items:
+ type: string
+ responses:
+ '200':
+ description: INCO sheets page
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/IncoListResponse'
+ '400':
+ $ref: '#/components/responses/BadRequest'
+ '401':
+ $ref: '#/components/responses/Unauthorized'
+ '429':
+ $ref: '#/components/responses/TooManyRequests'
+ '503':
+ $ref: '#/components/responses/ServiceUnavailable'
+
+ /inco-sheets/short:
+ get:
+ tags: [IncoSheets]
+ operationId: listIncoSheetsShort
+ summary: List INCO sheets (short payload)
+ parameters:
+ - $ref: '#/components/parameters/Page'
+ - $ref: '#/components/parameters/PageSize'
+ - $ref: '#/components/parameters/IncoSortBy'
+ - $ref: '#/components/parameters/SortDirection'
+ - name: brands
+ in: query
+ required: true
+ description: One or many brand codes
+ style: form
+ explode: true
+ schema:
+ type: array
+ minItems: 1
+ items:
+ type: string
+ responses:
+ '200':
+ description: INCO short page
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/IncoShortListResponse'
+ '400':
+ $ref: '#/components/responses/BadRequest'
+ '401':
+ $ref: '#/components/responses/Unauthorized'
+ '429':
+ $ref: '#/components/responses/TooManyRequests'
+ '503':
+ $ref: '#/components/responses/ServiceUnavailable'
+
+ /inco-sheets/search:
+ get:
+ tags: [IncoSheets]
+ operationId: searchIncoSheetsByIdLike
+ summary: Search INCO sheets by id-like pattern
+ parameters:
+ - name: incoIdLike
+ in: query
+ required: true
+ schema:
+ type: string
+ description: Pattern used with SQL-like matching rules
+ - name: brands
+ in: query
+ required: true
+ style: form
+ explode: true
+ schema:
+ type: array
+ minItems: 1
+ items:
+ type: string
+ - name: short
+ in: query
+ required: false
+ schema:
+ type: boolean
+ default: false
+ description: Return short projection when true
+ responses:
+ '200':
+ description: Search result (first page, size 50)
+ content:
+ application/json:
+ schema:
+ oneOf:
+ - $ref: '#/components/schemas/IncoListResponse'
+ - $ref: '#/components/schemas/IncoShortListResponse'
+ '400':
+ $ref: '#/components/responses/BadRequest'
+ '401':
+ $ref: '#/components/responses/Unauthorized'
+ '429':
+ $ref: '#/components/responses/TooManyRequests'
+ '503':
+ $ref: '#/components/responses/ServiceUnavailable'
+
+ /inco-sheets/{incoId}:
+ get:
+ tags: [IncoSheets]
+ operationId: getIncoSheetById
+ summary: Get INCO sheet by id
+ parameters:
+ - name: incoId
+ in: path
+ required: true
+ schema:
+ type: string
+ pattern: '^\\d{1,}$'
+ responses:
+ '200':
+ description: INCO sheet detail
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/IncoItemResponse'
+ '400':
+ $ref: '#/components/responses/BadRequest'
+ '401':
+ $ref: '#/components/responses/Unauthorized'
+ '404':
+ description: INCO not found
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/NotFoundResponse'
+ '429':
+ $ref: '#/components/responses/TooManyRequests'
+ '503':
+ $ref: '#/components/responses/ServiceUnavailable'
+
+ /inco-sheets/{incoId}/composition:
+ get:
+ tags: [IncoComposition]
+ operationId: getIncoCompositionByIncoId
+ summary: Get composition by INCO id
+ parameters:
+ - name: incoId
+ in: path
+ required: true
+ schema:
+ type: string
+ pattern: '^\\d{1,}$'
+ responses:
+ '200':
+ description: Composition detail
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/IncoCompoItemResponse'
+ '400':
+ $ref: '#/components/responses/BadRequest'
+ '401':
+ $ref: '#/components/responses/Unauthorized'
+ '404':
+ description: Composition not found
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/NotFoundResponse'
+ '429':
+ $ref: '#/components/responses/TooManyRequests'
+ '503':
+ $ref: '#/components/responses/ServiceUnavailable'
+
+ /inco-compositions/{incoCompoId}:
+ get:
+ tags: [IncoComposition]
+ operationId: getIncoCompositionById
+ summary: Get composition by composition id
+ parameters:
+ - name: incoCompoId
+ in: path
+ required: true
+ schema:
+ type: string
+ pattern: '^\\d{1,}$'
+ responses:
+ '200':
+ description: Composition detail
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/IncoCompoItemResponse'
+ '400':
+ $ref: '#/components/responses/BadRequest'
+ '401':
+ $ref: '#/components/responses/Unauthorized'
+ '404':
+ description: Composition not found
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/NotFoundResponse'
+ '429':
+ $ref: '#/components/responses/TooManyRequests'
+ '503':
+ $ref: '#/components/responses/ServiceUnavailable'
+
+components:
+ securitySchemes:
+ ArcadiaAuth:
+ type: apiKey
+ in: header
+ name: X-API-Key
+ description: |
+ Requests also require `X-API-Signature` and `X-Timestamp` headers.
+ Signature is computed from method, URI, body payload, shared secret, and timestamp.
+
+ parameters:
+ Page:
+ name: page
+ in: query
+ required: false
+ schema:
+ type: integer
+ minimum: 1
+ default: 1
+ description: 1-based page index
+
+ PageSize:
+ name: page_size
+ in: query
+ required: false
+ schema:
+ type: integer
+ minimum: 1
+ default: 50
+ maximum: 10000
+ description: Max records per page
+
+ Since:
+ name: since
+ in: query
+ required: false
+ schema:
+ type: string
+ format: date-time
+ description: RFC3339 timestamp lower bound (>=)
+
+ SortDirection:
+ name: sortDirection
+ in: query
+ required: false
+ schema:
+ type: string
+ enum: [asc, desc]
+ default: desc
+
+ EmployeeSortBy:
+ name: sortBy
+ in: query
+ required: false
+ schema:
+ type: string
+ enum:
+ - arcadiaId
+ - startDate
+ - endDate
+ - plannedEndDate
+ - createdAt
+ - updatedAt
+
+ IncoSortBy:
+ name: sortBy
+ in: query
+ required: false
+ schema:
+ type: string
+ enum:
+ - id
+ - createdAt
+ - updatedAt
+
+ responses:
+ BadRequest:
+ description: Invalid request
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ApiErrorResponse'
+
+ Unauthorized:
+ description: Authentication failed
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ApiErrorResponse'
+
+ TooManyRequests:
+ description: Rate limited
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ApiErrorResponse'
+
+ ServiceUnavailable:
+ description: Upstream service unavailable
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ApiErrorResponse'
+
+ schemas:
+ Employee:
+ type: object
+ additionalProperties: false
+ required:
+ - matriculePublique
+ - lastname
+ - firstname
+ - start_date
+ - establishment
+ - site
+ - service
+ - created_at
+ properties:
+ matriculePublique:
+ type: string
+ lastname:
+ type: string
+ firstname:
+ type: string
+ start_date:
+ type: string
+ format: date-time
+ end_date:
+ type: [string, 'null']
+ format: date-time
+ planned_end_date:
+ type: [string, 'null']
+ format: date-time
+ establishment:
+ type: string
+ site:
+ type: string
+ service:
+ type: string
+ created_at:
+ type: string
+ format: date-time
+ updated_at:
+ type: [string, 'null']
+ format: date-time
+
+ IncoBrand:
+ type: object
+ additionalProperties: false
+ required: [code, label]
+ properties:
+ code:
+ type: string
+ label:
+ type: string
+
+ Inco:
+ type: object
+ additionalProperties: false
+ required:
+ - id
+ - name
+ - libelle
+ - description
+ - allegations
+ - sellArguments
+ - preparationAdvices
+ - ingredients
+ - allergens
+ - brand
+ - isSeasonal
+ - additives
+ properties:
+ id:
+ type: string
+ pattern: '^\\d{1,}$'
+ name:
+ type: string
+ libelle:
+ type: string
+ description:
+ type: string
+ allegations:
+ type: object
+ additionalProperties: true
+ sellArguments:
+ type: string
+ preparationAdvices:
+ type: string
+ tips:
+ type: [string, 'null']
+ sellFamilly:
+ type: [string, 'null']
+ ingredients:
+ type: object
+ additionalProperties: true
+ portions:
+ type: [object, 'null']
+ additionalProperties: true
+ allergens:
+ type: array
+ items:
+ type: object
+ additionalProperties: true
+ brand:
+ $ref: '#/components/schemas/IncoBrand'
+ isSeasonal:
+ type: boolean
+ weight:
+ type: [object, 'null']
+ additionalProperties: true
+ nutriscore:
+ type: [object, 'null']
+ additionalProperties: true
+ storageCondition:
+ type: [object, 'null']
+ additionalProperties: true
+ additives:
+ type: array
+ items:
+ type: object
+ additionalProperties: true
+ compo:
+ type: [string, 'null']
+ pattern: '^\\d{1,}$'
+ created_at:
+ type: [string, 'null']
+ format: date-time
+ updated_at:
+ type: [string, 'null']
+ format: date-time
+
+ IncoShort:
+ type: object
+ additionalProperties: false
+ required:
+ - id
+ - name
+ - libelle
+ - description
+ properties:
+ id:
+ type: string
+ pattern: '^\\d{1,}$'
+ name:
+ type: string
+ libelle:
+ type: string
+ description:
+ type: string
+ created_at:
+ type: [string, 'null']
+ format: date-time
+ updated_at:
+ type: [string, 'null']
+ format: date-time
+
+ IncoCompo:
+ type: object
+ additionalProperties: false
+ required:
+ - id
+ - idInco
+ - identification
+ - energie
+ - macronutrimentsRef
+ - macronutrimentsPortion
+ - fnl
+ - apportsReference
+ - nutriScore
+ - pointsNutriScore
+ - mineraux
+ - vitamines
+ - glucidesDetail
+ - acideGras
+ - acidesAmines
+ - composesSpeciaux
+ properties:
+ id:
+ type: string
+ pattern: '^\\d{1,}$'
+ idInco:
+ type: string
+ pattern: '^\\d{1,}$'
+ identification:
+ type: object
+ additionalProperties: true
+ energie:
+ type: object
+ additionalProperties: true
+ macronutrimentsRef:
+ type: object
+ additionalProperties: true
+ macronutrimentsPortion:
+ type: object
+ additionalProperties: true
+ fnl:
+ type: object
+ additionalProperties: true
+ apportsReference:
+ type: object
+ additionalProperties: true
+ nutriScore:
+ type: object
+ additionalProperties: true
+ pointsNutriScore:
+ type: object
+ additionalProperties: true
+ mineraux:
+ type: object
+ additionalProperties: true
+ vitamines:
+ type: object
+ additionalProperties: true
+ glucidesDetail:
+ type: object
+ additionalProperties: true
+ acideGras:
+ type: object
+ additionalProperties: true
+ acidesAmines:
+ type: object
+ additionalProperties: true
+ composesSpeciaux:
+ type: object
+ additionalProperties: true
+
+ Pagination:
+ type: object
+ additionalProperties: false
+ required:
+ - page
+ - pageSize
+ - totalItems
+ - totalPages
+ - links
+ properties:
+ page:
+ type: integer
+ minimum: 1
+ pageSize:
+ type: integer
+ minimum: 1
+ totalItems:
+ type: integer
+ minimum: 0
+ totalPages:
+ type: integer
+ minimum: 0
+ links:
+ type: object
+ additionalProperties: false
+ required: [first, last]
+ properties:
+ first:
+ type: string
+ format: uri
+ last:
+ type: string
+ format: uri
+
+ EmployeeListResponse:
+ allOf:
+ - $ref: '#/components/schemas/SuccessEnvelope'
+ - type: object
+ properties:
+ data:
+ type: array
+ items:
+ $ref: '#/components/schemas/Employee'
+ pagination:
+ $ref: '#/components/schemas/Pagination'
+
+ EmployeeItemResponse:
+ allOf:
+ - $ref: '#/components/schemas/SuccessEnvelope'
+ - type: object
+ properties:
+ data:
+ $ref: '#/components/schemas/Employee'
+
+ IncoListResponse:
+ allOf:
+ - $ref: '#/components/schemas/SuccessEnvelope'
+ - type: object
+ properties:
+ data:
+ type: array
+ items:
+ $ref: '#/components/schemas/Inco'
+ pagination:
+ $ref: '#/components/schemas/Pagination'
+
+ IncoShortListResponse:
+ allOf:
+ - $ref: '#/components/schemas/SuccessEnvelope'
+ - type: object
+ properties:
+ data:
+ type: array
+ items:
+ $ref: '#/components/schemas/IncoShort'
+ pagination:
+ $ref: '#/components/schemas/Pagination'
+
+ IncoItemResponse:
+ allOf:
+ - $ref: '#/components/schemas/SuccessEnvelope'
+ - type: object
+ properties:
+ data:
+ $ref: '#/components/schemas/Inco'
+
+ IncoCompoItemResponse:
+ allOf:
+ - $ref: '#/components/schemas/SuccessEnvelope'
+ - type: object
+ properties:
+ data:
+ $ref: '#/components/schemas/IncoCompo'
+
+ SuccessEnvelope:
+ type: object
+ additionalProperties: false
+ required: [success, data]
+ properties:
+ success:
+ type: boolean
+ const: true
+ data: {}
+ pagination:
+ $ref: '#/components/schemas/Pagination'
+
+ ApiErrorCode:
+ type: string
+ enum:
+ - '0004'
+ - ERR_UNAUTHORIZED_PARAMETER
+ - ERR_DEFAULT
+ - ERR_LIST_SIZE_MISMATCH
+ - ERR_METAEXCEPTION
+ - ERR_SORT_LIST_SIZE_MISMATCH
+ - ERR_TABLE_NAME_MISSING
+ - ERR_UNAUTHORIZED_OPERATOR
+ - ERR_BAD_DATE_FORMAT
+ - ERR_PAGE_TYPE_MISMATCH
+ - ERR_PAGE_SIZE_TYPE_MISMATCH
+ - ERR_TOO_MANY_RECORDS
+ - ERR_INVALID_API_KEY
+ - ERR_INVALID_API_SIGNATURE
+ - ERR_TOO_MANY_REQUESTS
+ - UNKNOWN
+
+ ApiErrorObject:
+ type: object
+ additionalProperties: true
+ required: [code]
+ properties:
+ code:
+ $ref: '#/components/schemas/ApiErrorCode'
+ message:
+ type: string
+
+ ApiErrorResponse:
+ type: object
+ additionalProperties: false
+ required: [success, error]
+ properties:
+ success:
+ type: boolean
+ const: false
+ error:
+ oneOf:
+ - $ref: '#/components/schemas/ApiErrorObject'
+ - type: array
+ items:
+ $ref: '#/components/schemas/ApiErrorObject'
+
+ NotFoundResponse:
+ type: object
+ additionalProperties: false
+ required: [success, error]
+ properties:
+ success:
+ type: boolean
+ const: false
+ error:
+ type: object
+ additionalProperties: false
+ required: [code, message]
+ properties:
+ code:
+ type: string
+ enum: [NOT_FOUND]
+ message:
+ type: string
diff --git a/phpcs.xml b/phpcs.xml
new file mode 100644
index 0000000..4e5b3c6
--- /dev/null
+++ b/phpcs.xml
@@ -0,0 +1,67 @@
+
+
+
+ Standard optimisé : Analyse statique complémentaire à Pint.
+
+
+
+
+ src/
+ config/
+ database/
+ routes/
+
+ */vendor/*
+ */storage/*
+ _ide_helper.php
+ */tests/*
+ *.blade.php
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ */database/migrations/*
+
+
+
diff --git a/phpstan.neon b/phpstan.neon
new file mode 100644
index 0000000..660c642
--- /dev/null
+++ b/phpstan.neon
@@ -0,0 +1,16 @@
+includes:
+ - vendor/larastan/larastan/extension.neon
+ - vendor/nesbot/carbon/extension.neon
+ - vendor/pestphp/pest/extension.neon
+
+parameters:
+ paths:
+ - src/
+
+ excludePaths:
+ - tests/Architecture/
+
+ level: 10
+
+ # Enforce strict types analysis
+ treatPhpDocTypesAsCertain: false
diff --git a/phpunit.xml b/phpunit.xml
new file mode 100644
index 0000000..223c0a8
--- /dev/null
+++ b/phpunit.xml
@@ -0,0 +1,22 @@
+
+
+
+
+ tests/Unit
+
+
+ tests/Feature
+
+
+ tests/Architecture
+
+
+
+
+ src
+
+
+
+
+
+
diff --git a/pint.json b/pint.json
new file mode 100644
index 0000000..d270a74
--- /dev/null
+++ b/pint.json
@@ -0,0 +1,77 @@
+{
+ "preset": "laravel",
+ "rules": {
+ "indentation_type": true,
+ "single_line_empty_body": false,
+ "types_spaces": {
+ "space": "single",
+ "space_multiple_catch": "single"
+ },
+ "control_structure_braces": true,
+ "new_with_parentheses": {
+ "anonymous_class": true,
+ "named_class": true
+ },
+ "class_definition": {
+ "single_item_single_line": false,
+ "single_line": false,
+ "space_before_parenthesis": true
+ },
+ "curly_braces_position": {
+ "allow_single_line_empty_anonymous_classes": false,
+ "classes_opening_brace": "next_line_unless_newline_at_signature_end",
+ "anonymous_classes_opening_brace": "next_line_unless_newline_at_signature_end",
+ "control_structures_opening_brace": "same_line",
+ "functions_opening_brace": "next_line_unless_newline_at_signature_end",
+ "anonymous_functions_opening_brace": "same_line"
+ },
+ "binary_operator_spaces": {
+ "default": "align_single_space_minimal",
+ "operators": {
+ "=": "align_single_space",
+ "|": "single_space",
+ "=>": "align_single_space",
+ ".=": "align_single_space"
+ }
+ },
+ "concat_space": {
+ "spacing": "one"
+ },
+ "align_multiline_comment": {
+ "comment_type": "all_multiline"
+ },
+ "array_indentation": true,
+ "method_chaining_indentation": true,
+ "statement_indentation": {
+ "stick_comment_to_next_continuous_control_statement": true
+ },
+ "no_unused_imports": true,
+ "fully_qualified_strict_types": {
+ "import_symbols": true,
+ "leading_backslash_in_global_namespace": true,
+ "phpdoc_tags": []
+ },
+ "visibility_required": {
+ "elements": [
+ "const",
+ "method",
+ "property"
+ ]
+ },
+ "no_useless_else": true,
+ "function_declaration": {
+ "closure_function_spacing": "one",
+ "closure_fn_spacing": "one",
+ "trailing_comma_single_line": false
+ },
+ "single_line_after_imports": true,
+ "combine_consecutive_issets": true,
+ "array_syntax": {
+ "syntax": "short"
+ },
+ "single_quote": true,
+ "blank_line_after_namespace": true,
+ "blank_line_after_opening_tag": true,
+ "declare_strict_types": true
+ }
+}
diff --git a/public/.htaccess b/public/.htaccess
new file mode 100644
index 0000000..b574a59
--- /dev/null
+++ b/public/.htaccess
@@ -0,0 +1,25 @@
+
+
+ Options -MultiViews -Indexes
+
+
+ RewriteEngine On
+
+ # Handle Authorization Header
+ RewriteCond %{HTTP:Authorization} .
+ RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
+
+ # Handle X-XSRF-Token Header
+ RewriteCond %{HTTP:x-xsrf-token} .
+ RewriteRule .* - [E=HTTP_X_XSRF_TOKEN:%{HTTP:X-XSRF-Token}]
+
+ # Redirect Trailing Slashes If Not A Folder...
+ RewriteCond %{REQUEST_FILENAME} !-d
+ RewriteCond %{REQUEST_URI} (.+)/$
+ RewriteRule ^ %1 [L,R=301]
+
+ # Send Requests To Front Controller...
+ RewriteCond %{REQUEST_FILENAME} !-d
+ RewriteCond %{REQUEST_FILENAME} !-f
+ RewriteRule ^ index.php [L]
+
diff --git a/public/favicon.ico b/public/favicon.ico
new file mode 100644
index 0000000..e69de29
diff --git a/public/index.php b/public/index.php
new file mode 100644
index 0000000..91122d2
--- /dev/null
+++ b/public/index.php
@@ -0,0 +1,21 @@
+handleRequest(Request::capture());
diff --git a/public/robots.txt b/public/robots.txt
new file mode 100644
index 0000000..eb05362
--- /dev/null
+++ b/public/robots.txt
@@ -0,0 +1,2 @@
+User-agent: *
+Disallow:
diff --git a/rector.php b/rector.php
new file mode 100644
index 0000000..e484bd1
--- /dev/null
+++ b/rector.php
@@ -0,0 +1,34 @@
+withSetProviders(LaravelSetProvider::class)
+ ->withPaths([
+ __DIR__ . '/src',
+ __DIR__ . '/bootstrap',
+ __DIR__ . '/config',
+ __DIR__ . '/public',
+ __DIR__ . '/resources',
+ __DIR__ . '/routes',
+ __DIR__ . '/tests',
+ ])
+ ->withPhpSets()
+ ->withComposerBased(laravel: true)
+ ->withSets([
+ LaravelLevelSetList::UP_TO_LARAVEL_130,
+ LaravelSetList::LARAVEL_CODE_QUALITY,
+ LaravelSetList::LARAVEL_COLLECTION,
+ LaravelSetList::LARAVEL_IF_HELPERS,
+ LaravelSetList::LARAVEL_LEGACY_FACTORIES_TO_CLASSES,
+ LaravelSetList::LARAVEL_TYPE_DECLARATIONS,
+ LaravelSetList::LARAVEL_ELOQUENT_MAGIC_METHOD_TO_QUERY_BUILDER,
+ ])
+ ->withTypeCoverageLevel(0)
+ ->withDeadCodeLevel(0)
+ ->withCodeQualityLevel(0);
diff --git a/routes/api.php b/routes/api.php
new file mode 100644
index 0000000..28e2fa4
--- /dev/null
+++ b/routes/api.php
@@ -0,0 +1,15 @@
+ response()->json(Config::string('app.name') . ' choose a version'))
+ ->name('api.root');
+
+// * V1 API
+Route::prefix('v1')->name('api.v1.')->group(function () {
+ require __DIR__ . '/apiv1.php';
+});
diff --git a/routes/apiv1.php b/routes/apiv1.php
new file mode 100644
index 0000000..3148ee2
--- /dev/null
+++ b/routes/apiv1.php
@@ -0,0 +1,21 @@
+ response()->json(Config::string('app.name') . ' v1'))->name('root');
+
+Route::get('/ping', fn () => response()->json('pong'))->name('ping');
+
+Route::get('/openapi', function () {
+ return response()->file(
+ base_path('documentation/OpenApi/openapi.yaml'),
+ ['Content-Type' => 'application/yaml']
+ );
+})->name('openapi');
+Route::get('/employees', EmployeesIndexController::class)->name('employees.index');
+Route::get('/employees/{employeeId}', EmployeeShowController::class)->name('employees.show');
diff --git a/routes/console.php b/routes/console.php
new file mode 100644
index 0000000..174d7fd
--- /dev/null
+++ b/routes/console.php
@@ -0,0 +1,3 @@
+name('home');
+Route::get('/errors/{code}', ErrorDocumentationController::class)->name('errors.doc');
diff --git a/src/Application/Usecase/Employees/Find/EmployeeShowPresenter.php b/src/Application/Usecase/Employees/Find/EmployeeShowPresenter.php
new file mode 100644
index 0000000..0035a25
--- /dev/null
+++ b/src/Application/Usecase/Employees/Find/EmployeeShowPresenter.php
@@ -0,0 +1,20 @@
+ */
+final readonly class EmployeeShowPresenter implements Presenter
+{
+ #[\Override]
+ public function present(UsecaseOutput $output): object
+ {
+ assert($output instanceof Output);
+
+ return EmployeeShowView::fromOutput($output);
+ }
+}
diff --git a/src/Application/Usecase/Employees/Find/EmployeeShowView.php b/src/Application/Usecase/Employees/Find/EmployeeShowView.php
new file mode 100644
index 0000000..0f4f7e0
--- /dev/null
+++ b/src/Application/Usecase/Employees/Find/EmployeeShowView.php
@@ -0,0 +1,38 @@
+id,
+ firstName: $output->firstName,
+ lastName: $output->lastName,
+ establishment: $output->establishment,
+ site: $output->site,
+ service: $output->service,
+ startDate: $output->startDate,
+ endDate: $output->endDate,
+ plannedEndDate: $output->plannedEndDate,
+ );
+ }
+}
diff --git a/src/Application/Usecase/Employees/Find/FindEmployee.php b/src/Application/Usecase/Employees/Find/FindEmployee.php
new file mode 100644
index 0000000..57dab15
--- /dev/null
+++ b/src/Application/Usecase/Employees/Find/FindEmployee.php
@@ -0,0 +1,43 @@
+ */
+final readonly class FindEmployee implements Usecase
+{
+ public function __construct(
+ private EmployeeDirectory $directory
+ ) {
+ }
+
+ #[\Override]
+ public function execute(BaseInput $input): Output
+ {
+ assert($input instanceof Input);
+
+ $employee = $this->directory->find($input->id);
+
+ if ($employee === null) {
+ throw NotFoundException::forEntity('Employee', (string) $input->id);
+ }
+
+ return new Output(
+ id: $employee->id(),
+ firstName: $employee->firstName,
+ lastName: $employee->lastName,
+ establishment: $employee->establishment->value,
+ site: $employee->site->value,
+ service: $employee->service->value,
+ startDate: $employee->startDate,
+ endDate: $employee->endDate,
+ plannedEndDate: $employee->plannedEndDate,
+ );
+ }
+}
diff --git a/src/Application/Usecase/Employees/Find/Input.php b/src/Application/Usecase/Employees/Find/Input.php
new file mode 100644
index 0000000..1258c7e
--- /dev/null
+++ b/src/Application/Usecase/Employees/Find/Input.php
@@ -0,0 +1,16 @@
+ */
+final readonly class EmployeesIndexPresenter implements Presenter
+{
+ #[\Override]
+ public function present(UsecaseOutput $output): object
+ {
+ assert($output instanceof Output);
+
+ return EmployeesIndexView::fromOutput($output);
+ }
+}
diff --git a/src/Application/Usecase/Employees/FindAll/EmployeesIndexView.php b/src/Application/Usecase/Employees/FindAll/EmployeesIndexView.php
new file mode 100644
index 0000000..c263064
--- /dev/null
+++ b/src/Application/Usecase/Employees/FindAll/EmployeesIndexView.php
@@ -0,0 +1,32 @@
+employees as $employee) {
+ assert($employee instanceof PaginatedEmployee);
+ }
+ }
+
+ public static function fromOutput(Output $output): self
+ {
+ return new self(
+ employees: $output->employees,
+ total: $output->total,
+ page: $output->page,
+ perPage: $output->perPage,
+ );
+ }
+}
diff --git a/src/Application/Usecase/Employees/FindAll/FindAllEmployees.php b/src/Application/Usecase/Employees/FindAll/FindAllEmployees.php
new file mode 100644
index 0000000..6e91bfa
--- /dev/null
+++ b/src/Application/Usecase/Employees/FindAll/FindAllEmployees.php
@@ -0,0 +1,53 @@
+ */
+final readonly class FindAllEmployees implements Usecase
+{
+ public function __construct(
+ private EmployeeDirectory $directory
+ ) {
+ }
+
+ #[\Override]
+ public function execute(BaseInput $input): Output
+ {
+ assert($input instanceof Input);
+
+ $page = $this->directory->findAll(
+ $input->pagination,
+ $input->sorter
+ );
+
+ return $this->toOutput($page);
+ }
+
+ /**
+ * @param Paginated $resultPage
+ */
+ private function toOutput(Paginated $resultPage): Output
+ {
+ $pagination = $resultPage->getPagination();
+
+ return new Output(
+ employees: array_map([$this, 'toPaginatedEmployee'], $resultPage->getItems()),
+ total: $resultPage->getTotal(),
+ page: $pagination->pageNumber(),
+ perPage: $pagination->pageSize(),
+ );
+ }
+
+ private function toPaginatedEmployee(Employee $employee): PaginatedEmployee
+ {
+ return PaginatedEmployee::fromDomain($employee);
+ }
+}
diff --git a/src/Application/Usecase/Employees/FindAll/Input.php b/src/Application/Usecase/Employees/FindAll/Input.php
new file mode 100644
index 0000000..94e31c0
--- /dev/null
+++ b/src/Application/Usecase/Employees/FindAll/Input.php
@@ -0,0 +1,18 @@
+employees as $employee) {
+ assert($employee instanceof PaginatedEmployee);
+ }
+ }
+}
diff --git a/src/Application/Usecase/Employees/FindAll/PaginatedEmployee.php b/src/Application/Usecase/Employees/FindAll/PaginatedEmployee.php
new file mode 100644
index 0000000..ab6d9de
--- /dev/null
+++ b/src/Application/Usecase/Employees/FindAll/PaginatedEmployee.php
@@ -0,0 +1,40 @@
+id(),
+ $employee->firstName,
+ $employee->lastName,
+ $employee->establishment->value,
+ $employee->site->value,
+ $employee->service->value,
+ $employee->startDate,
+ $employee->endDate,
+ $employee->plannedEndDate,
+ );
+ }
+}
diff --git a/src/Domain/Exceptions/NotFoundException.php b/src/Domain/Exceptions/NotFoundException.php
new file mode 100644
index 0000000..319ed00
--- /dev/null
+++ b/src/Domain/Exceptions/NotFoundException.php
@@ -0,0 +1,13 @@
+ */
+final readonly class Employee implements Entity
+{
+ public function __construct(
+ public ArcadiaEmployeeId $publicEmployeeNumber,
+ public string $lastName,
+ public string $firstName,
+ public \DateTimeInterface $startDate,
+ public ?\DateTimeInterface $endDate,
+ public ?\DateTimeInterface $plannedEndDate,
+ public EstablishmentCode $establishment,
+ public SiteId $site,
+ public ServiceId $service,
+ public \DateTimeInterface $createdAt,
+ public ?\DateTimeInterface $updatedAt,
+ ) {
+ }
+
+ #[\Override]
+ public function id(): ArcadiaEmployeeId
+ {
+ return $this->publicEmployeeNumber;
+ }
+}
diff --git a/src/Domain/Models/ValueObjects/BrandCode.php b/src/Domain/Models/ValueObjects/BrandCode.php
new file mode 100644
index 0000000..3caeb7f
--- /dev/null
+++ b/src/Domain/Models/ValueObjects/BrandCode.php
@@ -0,0 +1,21 @@
+ Sans marque
+ */
+final readonly class BrandCode
+{
+ public function __construct(
+ public readonly int $value
+ ) {
+ if ($value <= 0) {
+ throw new \DomainException(
+ "Invalid code '{$value}' shall be greater than 0"
+ );
+ }
+ }
+}
diff --git a/src/Domain/Models/ValueObjects/Employees/EmployeeSortColumn.php b/src/Domain/Models/ValueObjects/Employees/EmployeeSortColumn.php
new file mode 100644
index 0000000..8cdb91a
--- /dev/null
+++ b/src/Domain/Models/ValueObjects/Employees/EmployeeSortColumn.php
@@ -0,0 +1,15 @@
+code = $code;
+ $trimmedLabel = trim($label);
+
+ if (! preg_match('/^E\d+(?:[a-z]+(?:\([ivx]+\))?)?$/', $this->code)) {
+ throw new \DomainException(
+ "Invalid additive code '{$code}': must match E-number format (e.g. E300, E471a, E160ai, E160a(ii), E1404)"
+ );
+ }
+
+ if ($trimmedLabel === '') {
+ throw new \DomainException(
+ "Invalid label for additive '{$code}': must not be empty"
+ );
+ }
+ }
+
+ public function jsonSerialize(): mixed
+ {
+ return [
+ 'code' => $this->code,
+ 'label' => $this->label,
+ ];
+ }
+}
diff --git a/src/Domain/Models/ValueObjects/Inco/Allegations.php b/src/Domain/Models/ValueObjects/Inco/Allegations.php
new file mode 100644
index 0000000..38e6841
--- /dev/null
+++ b/src/Domain/Models/ValueObjects/Inco/Allegations.php
@@ -0,0 +1,85 @@
+allegations = \array_filter($allegations, fn ($el) => ! empty($el));
+ $this->health = \array_filter($health, fn ($el) => ! empty($el));
+ $this->nutrition = \array_filter($nutrition, fn ($el) => ! empty($el));
+ $this->other = \array_filter($other, fn ($el) => ! empty($el));
+ }
+
+ // * Methods
+
+ /**
+ * @return string[]
+ */
+ public function allegations(): array
+ {
+ return [...$this->allegations];
+ }
+
+ /**
+ * @return string[]
+ */
+ public function health(): array
+ {
+ return [...$this->health];
+ }
+
+ /**
+ * @return string[]
+ */
+ public function nutrition(): array
+ {
+ return [...$this->nutrition];
+ }
+
+ /**
+ * @return string[]
+ */
+ public function other(): array
+ {
+ return [...$this->other];
+ }
+
+ public function jsonSerialize(): mixed
+ {
+ return [
+ 'allegations' => [...$this->allegations],
+ 'health' => [...$this->health],
+ 'nutrition' => [...$this->nutrition],
+ 'other' => [...$this->other],
+ ];
+ }
+}
diff --git a/src/Domain/Models/ValueObjects/Inco/Allergen.php b/src/Domain/Models/ValueObjects/Inco/Allergen.php
new file mode 100644
index 0000000..a5ed2d6
--- /dev/null
+++ b/src/Domain/Models/ValueObjects/Inco/Allergen.php
@@ -0,0 +1,33 @@
+ $this->code,
+ 'label' => $this->label,
+ ];
+ }
+}
diff --git a/src/Domain/Models/ValueObjects/Inco/IncoWeight.php b/src/Domain/Models/ValueObjects/Inco/IncoWeight.php
new file mode 100644
index 0000000..b21fd40
--- /dev/null
+++ b/src/Domain/Models/ValueObjects/Inco/IncoWeight.php
@@ -0,0 +1,29 @@
+ $this->netUvc,
+ 'brutUvc' => $this->brutUvc,
+ 'moyTheo' => $this->moyTheo,
+ ];
+ }
+}
diff --git a/src/Domain/Models/ValueObjects/Inco/Ingredients.php b/src/Domain/Models/ValueObjects/Inco/Ingredients.php
new file mode 100644
index 0000000..bfa1881
--- /dev/null
+++ b/src/Domain/Models/ValueObjects/Inco/Ingredients.php
@@ -0,0 +1,52 @@
+ list of ingredient strings without a section label
+ * - a labelled group (string key) -> list of ingredient strings under a section label
+ * (e.g. "Ingrédients", "Traces possibles")
+ *
+ * @phpstan-type IngredientGroup array
+ */
+final readonly class Ingredients
+{
+ /**
+ * @param array $groups
+ */
+ public function __construct(
+ public readonly array $groups
+ ) {
+ foreach ($groups as $key => $lines) {
+ if (! is_array($lines)) {
+ throw new \DomainException(
+ "Invalid ingredient group at key '{$key}': value must be an array of strings"
+ );
+ }
+
+ foreach ($lines as $i => $line) {
+ if (! is_string($line)) {
+ throw new \DomainException(
+ "Invalid ingredient at group '{$key}', index '{$i}': value must be a string"
+ );
+ }
+
+ if (empty(trim($line))) {
+ throw new \DomainException(
+ "Invalid ingredient at group '{$key}', index '{$i}': string should not be empty"
+ );
+ }
+ }
+ }
+ }
+
+ public function jsonSerialize(): mixed
+ {
+ return $this->groups;
+ }
+}
diff --git a/src/Domain/Models/ValueObjects/Inco/Nutriscore.php b/src/Domain/Models/ValueObjects/Inco/Nutriscore.php
new file mode 100644
index 0000000..fb4e332
--- /dev/null
+++ b/src/Domain/Models/ValueObjects/Inco/Nutriscore.php
@@ -0,0 +1,34 @@
+grade, self::VALID_GRADES, true)) {
+ throw new \DomainException(
+ sprintf(
+ "Invalid Nutri-Score grade '%s': must be one of %s",
+ $grade,
+ implode(', ', self::VALID_GRADES)
+ )
+ );
+ }
+ }
+
+ public function jsonSerialize(): mixed
+ {
+ return $this->grade;
+ }
+}
diff --git a/src/Domain/Models/ValueObjects/Inco/PortionAmount.php b/src/Domain/Models/ValueObjects/Inco/PortionAmount.php
new file mode 100644
index 0000000..ef7e51b
--- /dev/null
+++ b/src/Domain/Models/ValueObjects/Inco/PortionAmount.php
@@ -0,0 +1,88 @@
+ $maxValue)) {
+ throw new \InvalidArgumentException("lowPart must be between 0 and '{$maxValue}', given '{$lowPart}'");
+ }
+ if ($highPart < 0.0 || ($highPart > $maxValue)) {
+ throw new \InvalidArgumentException("highPart must be between 0 and '{$maxValue}', given '{$highPart}'");
+ }
+
+ $this->lowPart = (int) bcmul((string) $lowPart, (string) $scale, 0);
+ $this->highPart = (int) bcmul((string) $highPart, (string) $scale, 0);
+ $this->approximative = $approximative;
+ }
+
+ public function lowPart(): int
+ {
+ return $this->lowPart;
+ }
+
+ public function highPart(): int
+ {
+ return $this->highPart;
+ }
+
+ public function approximative(): bool
+ {
+ return $this->approximative;
+ }
+
+ /**
+ * @return array{lowPart: int, highPart: int, approximative: bool}
+ */
+ public function jsonSerialize(): array
+ {
+ return [
+ 'lowPart' => $this->lowPart,
+ 'highPart' => $this->highPart,
+ 'approximative' => $this->approximative,
+ ];
+ }
+}
diff --git a/src/Domain/Models/ValueObjects/Inco/PortionType.php b/src/Domain/Models/ValueObjects/Inco/PortionType.php
new file mode 100644
index 0000000..f8e78dc
--- /dev/null
+++ b/src/Domain/Models/ValueObjects/Inco/PortionType.php
@@ -0,0 +1,31 @@
+value) {
+ self::approximative->name => 'approximatif',
+ self::exact->name => 'exact',
+ self::unknown->name => 'inconnue',
+ default => 'inconnue',
+ };
+ }
+
+ public function jsonSerialize(): mixed
+ {
+ return [
+ 'value' => $this->value,
+ 'name' => $this->name,
+ 'description' => $this->description(),
+ ];
+ }
+}
diff --git a/src/Domain/Models/ValueObjects/Inco/StorageCondition.php b/src/Domain/Models/ValueObjects/Inco/StorageCondition.php
new file mode 100644
index 0000000..c0c41de
--- /dev/null
+++ b/src/Domain/Models/ValueObjects/Inco/StorageCondition.php
@@ -0,0 +1,28 @@
+instructions))) {
+ throw new \DomainException(
+ 'Invalid instructions: must not be empty'
+ );
+ }
+ }
+
+ public function jsonSerialize(): mixed
+ {
+ return $this->instructions;
+ }
+}
diff --git a/src/Domain/Models/ValueObjects/IncoCompo/AbstractIncoCompoPartDto.php b/src/Domain/Models/ValueObjects/IncoCompo/AbstractIncoCompoPartDto.php
new file mode 100644
index 0000000..f4c71a7
--- /dev/null
+++ b/src/Domain/Models/ValueObjects/IncoCompo/AbstractIncoCompoPartDto.php
@@ -0,0 +1,14 @@
+ */
+interface EmployeeDirectory extends Directory
+{
+ /** @return Paginated */
+ public function findAll(Pagination $pagination, EmployeeSorter $sorter): Paginated;
+
+ public function find(ArcadiaEmployeeId $id): ?Employee;
+}
diff --git a/src/Infra/Adapters/Directories/EloquentEmployeeDirectory.php b/src/Infra/Adapters/Directories/EloquentEmployeeDirectory.php
new file mode 100644
index 0000000..1c24d62
--- /dev/null
+++ b/src/Infra/Adapters/Directories/EloquentEmployeeDirectory.php
@@ -0,0 +1,118 @@
+count();
+
+ /** @var \Illuminate\Support\Collection $rows */
+ $rows = (clone $query)
+ ->orderBy(
+ $this->toSqlColumn($sorter->sortBy),
+ $sorter->direction
+ )
+ ->offset($pagination->from())
+ ->limit($pagination->pageSize())
+ ->get();
+
+ $items = [];
+
+ foreach ($rows as $row) {
+ $items[] = $this->toDomain($row);
+ }
+
+ /** @var Employee[] $items */
+ return new Paginated($pagination, $items, $total);
+ }
+
+ #[\Override]
+ public function find(ArcadiaEmployeeId $id): ?Employee
+ {
+ $model = EmployeeModel::query()
+ ->where('public_employee_number', $id->value)
+ ->first();
+
+ if ($model === null) {
+ return null;
+ }
+
+ return $this->toDomain($model);
+ }
+
+ private function toDomain(EmployeeModel $employee): Employee
+ {
+ $createdAt = $this->toNullableDateTime($employee->created_at);
+
+ if ($createdAt === null) {
+ throw new \UnexpectedValueException('Employee created_at cannot be null.');
+ }
+
+ return new Employee(
+ publicEmployeeNumber: new ArcadiaEmployeeId((string) $employee->public_employee_number),
+ lastName: (string) $employee->last_name,
+ firstName: (string) $employee->first_name,
+ startDate: $this->toDateTime($employee->start_date),
+ endDate: $this->toNullableDateTime($employee->end_date),
+ plannedEndDate: $this->toNullableDateTime($employee->planned_end_date),
+ establishment: new EstablishmentCode((string) $employee->establishment),
+ site: new SiteId((string) $employee->site),
+ service: new ServiceId((string) $employee->service),
+ createdAt: $createdAt,
+ updatedAt: $this->toNullableDateTime($employee->updated_at),
+ );
+ }
+
+ private function toDateTime(\DateTimeInterface | string $value): \DateTimeInterface
+ {
+ if ($value instanceof \DateTimeInterface) {
+ return $value;
+ }
+
+ return new \DateTimeImmutable($value);
+ }
+
+ private function toNullableDateTime(mixed $value): ?\DateTimeInterface
+ {
+ if ($value === null) {
+ return null;
+ }
+
+ if ($value instanceof \DateTimeInterface || is_string($value)) {
+ return $this->toDateTime($value);
+ }
+
+ throw new \UnexpectedValueException('Invalid datetime value type.');
+ }
+
+ private function toSqlColumn(EmployeeSortColumn $sortBy): string
+ {
+ return match ($sortBy) {
+ EmployeeSortColumn::arcadiaId => 'public_employee_number',
+ EmployeeSortColumn::startDate => 'start_date',
+ EmployeeSortColumn::endDate => 'end_date',
+ EmployeeSortColumn::plannedEndDate => 'planned_end_date',
+ EmployeeSortColumn::createdAt => 'created_at',
+ EmployeeSortColumn::updatedAt => 'updated_at',
+ };
+ }
+}
diff --git a/src/Infra/Database/Models/ApiClient.php b/src/Infra/Database/Models/ApiClient.php
new file mode 100644
index 0000000..735efb8
--- /dev/null
+++ b/src/Infra/Database/Models/ApiClient.php
@@ -0,0 +1,33 @@
+ */
+ use HasFactory;
+
+ protected static function newFactory(): EmployeeFactory
+ {
+ return EmployeeFactory::new();
+ }
+
+ #[\Override]
+ public function getConnectionName(): string
+ {
+ return Config::string('database.arcadia_meta_model');
+ }
+
+ protected $table = 'employees';
+
+ protected $primaryKey = 'public_employee_number';
+
+ public $incrementing = false;
+
+ protected $keyType = 'string';
+
+ protected $fillable = [
+ 'public_employee_number',
+ 'last_name',
+ 'first_name',
+ 'start_date',
+ 'end_date',
+ 'planned_end_date',
+ 'establishment',
+ 'site',
+ 'service',
+ ];
+
+ /** @return array */
+ #[\Override]
+ protected function casts(): array
+ {
+ return [
+ 'start_date' => 'date',
+ 'end_date' => 'date',
+ 'planned_end_date' => 'date',
+ 'created_at' => 'datetime',
+ 'updated_at' => 'datetime',
+ ];
+ }
+}
diff --git a/src/Infra/Http/Middleware/VerifyHmacSignature.php b/src/Infra/Http/Middleware/VerifyHmacSignature.php
new file mode 100644
index 0000000..58b9ae0
--- /dev/null
+++ b/src/Infra/Http/Middleware/VerifyHmacSignature.php
@@ -0,0 +1,62 @@
+header('X-Client-Id');
+ $timestamp = (int) $request->header('X-Timestamp');
+ $signature = $request->header('X-Signature');
+
+ if (! $clientId || ! $timestamp || ! $signature) {
+ return response()->json(['error' => 'Headers d\'authentification manquants.'], 401);
+ }
+
+ if (! is_string($clientId) || ! is_string($signature)) {
+ return response()->json(['error' => 'Headers d\'authentification invalides.'], 401);
+ }
+
+ if (abs(time() - $timestamp) > self::TIMESTAMP_TOLERANCE_SECONDS) {
+ return response()->json(['error' => 'Requête expirée (horodatage invalide).'], 401);
+ }
+
+ $client = ApiClient::query()->where('client_id', $clientId)
+ ->where('is_active', true)
+ ->first();
+
+ if (! $client) {
+ return response()->json(['error' => 'Client non identifié ou inactif.'], 401);
+ }
+
+ $payload = implode('|', [
+ strtoupper($request->method()),
+ $request->getRequestUri(),
+ $timestamp,
+ $request->getContent(),
+ ]);
+
+ $expectedSignature = hash_hmac('sha256', $payload, $client->secret);
+
+ if (! hash_equals($expectedSignature, $signature)) {
+ return response()->json(['error' => 'Signature HMAC invalide.'], 401);
+ }
+
+ $request->setUserResolver(fn () => $client);
+
+ return $next($request);
+ }
+}
diff --git a/src/Infra/Providers/AppServiceProvider.php b/src/Infra/Providers/AppServiceProvider.php
new file mode 100644
index 0000000..3db49f3
--- /dev/null
+++ b/src/Infra/Providers/AppServiceProvider.php
@@ -0,0 +1,121 @@
+environment('local'));
+
+ URL::forceScheme('https');
+
+ foreach ([\LC_TIME, \LC_MESSAGES, \LC_COLLATE, \LC_CTYPE, \LC_MONETARY] as $constant) {
+ setlocale(
+ $constant,
+ sprintf(
+ '%s_%s.UTF-8',
+ Config::string('app.locale'),
+ strtoupper(Config::string('app.locale'))
+ )
+ );
+ }
+
+ Date::setLocale(Config::string('app.locale'));
+ Date::setFallbackLocale(Config::string('app.fallback_locale'));
+
+ $provider = $this;
+
+ Date::macro('toLocalInput', function (CarbonInterface | \DateTimeInterface | int | float | string | null $date) use ($provider): ?string {
+ return $provider->toLocalInput($date);
+ });
+
+ Date::macro('forHumans', function (CarbonInterface | \DateTimeInterface | int | float | string | null $date) use ($provider): ?string {
+ return $provider->forHumans($date);
+ });
+
+ Request::macro('pagination', function (int $defaultPageSize = 25) use ($provider): Pagination {
+ return $provider->pagination(request(), $defaultPageSize);
+ });
+
+ Request::macro('toLeagueUri', function () use ($provider): Http {
+ return $provider->toLeagueUri(request());
+ });
+
+ Request::macro('toLeagueFullUri', function () use ($provider): Http {
+ return $provider->toLeagueFullUri(request());
+ });
+ }
+
+ public function toLocalInput(CarbonInterface | \DateTimeInterface | int | float | string | null $date): ?string
+ {
+ if ($date === null) {
+ return null;
+ }
+
+ $timezone = request()->string('client_timezone', 'Europe/Paris')->value();
+
+ return Date::parse($date)
+ ->setTimezone($timezone)
+ ->format('Y-m-d\TH:i');
+ }
+
+ public function forHumans(CarbonInterface | \DateTimeInterface | int | float | string | null $date): ?string
+ {
+ if ($date === null) {
+ return null;
+ }
+
+ $timezone = request()->string('client_timezone', 'Europe/Paris')->value();
+
+ return Date::parse($date)
+ ->setTimezone($timezone)
+ ->isoFormat('ddd DD/MM/Y \à HH:mm');
+ }
+
+ public function pagination(HttpRequest $request, int $defaultPageSize): Pagination
+ {
+ if ($request->has('offset') || $request->has('limit')) {
+ return Pagination::ofOffsetAndLimit(
+ $request->integer('offset', 0),
+ $request->integer('limit', $defaultPageSize)
+ );
+ }
+
+ $pageSize = $request->integer(
+ 'pageSize',
+ $request->integer('per_page', $request->integer('pagination', $defaultPageSize))
+ );
+
+ return Pagination::ofPage(
+ $request->integer('page', 1),
+ $pageSize
+ );
+ }
+
+ public function toLeagueUri(HttpRequest $request): Http
+ {
+ return Http::new($request->url());
+ }
+
+ public function toLeagueFullUri(HttpRequest $request): Http
+ {
+ return Http::new($request->fullUrl());
+ }
+}
diff --git a/src/Infra/Providers/DomainServiceProvider.php b/src/Infra/Providers/DomainServiceProvider.php
new file mode 100644
index 0000000..b99d1c0
--- /dev/null
+++ b/src/Infra/Providers/DomainServiceProvider.php
@@ -0,0 +1,21 @@
+app->bind(EmployeeDirectory::class, EloquentEmployeeDirectory::class);
+ $this->app->singleton(UsecaseExecutor::class, LaravelExecutor::class);
+ }
+}
diff --git a/src/Infra/Usecase/LaravelExecutor.php b/src/Infra/Usecase/LaravelExecutor.php
new file mode 100644
index 0000000..4c06696
--- /dev/null
+++ b/src/Infra/Usecase/LaravelExecutor.php
@@ -0,0 +1,57 @@
+ */
+final readonly class LaravelExecutor implements UsecaseExecutor
+{
+ public function __construct(
+ private DatabaseManager $database,
+ private LoggerInterface $logger,
+ ) {
+ }
+
+ /**
+ * @param Usecase $usecase
+ * @param Presenter<\Shared\DDD\Usecase\Output,object> $presenter
+ */
+ #[\Override]
+ public function execute(Usecase $usecase, Input $input, Presenter $presenter): object
+ {
+ $context = [
+ 'usecase' => $usecase::class,
+ 'input' => $input::class,
+ 'presenter' => $presenter::class,
+ ];
+
+ $this->logger->debug('Usecase execution started', $context);
+
+ try {
+ /** @var object $result */
+ $result = $this->database->transaction(function () use ($usecase, $input, $presenter): object {
+ $output = $usecase->execute($input);
+
+ return $presenter->present($output);
+ });
+
+ $this->logger->info('Usecase execution succeeded', $context);
+
+ return $result;
+ } catch (\Throwable $exception) {
+ $this->logger->error('Usecase execution failed', $context + [
+ 'exception' => $exception,
+ ]);
+
+ throw $exception;
+ }
+ }
+}
diff --git a/src/Presentation/Api/Exceptions/ApiExceptionDispatcher.php b/src/Presentation/Api/Exceptions/ApiExceptionDispatcher.php
new file mode 100644
index 0000000..0863c10
--- /dev/null
+++ b/src/Presentation/Api/Exceptions/ApiExceptionDispatcher.php
@@ -0,0 +1,32 @@
+is('api/*') && ! $request->wantsJson()) {
+ return null;
+ }
+
+ if ($request->is('api/v1/*') || $request->is('api/v1')) {
+ return $this->v1Renderer->render($e, $request);
+ }
+
+ // Fallback for unversioned api/* requests -> default to V1
+ return $this->v1Renderer->render($e, $request);
+ }
+}
diff --git a/src/Presentation/Api/V1/Contracts/ApiResponse.php b/src/Presentation/Api/V1/Contracts/ApiResponse.php
new file mode 100644
index 0000000..352e467
--- /dev/null
+++ b/src/Presentation/Api/V1/Contracts/ApiResponse.php
@@ -0,0 +1,12 @@
+id,
+ firstName: $view->firstName,
+ lastName: $view->lastName,
+ establishment: $view->establishment,
+ site: $view->site,
+ service: $view->service,
+ startDate: $view->startDate->format('Y-m-d'),
+ endDate: $view->endDate?->format('Y-m-d'),
+ plannedEndDate: $view->plannedEndDate?->format('Y-m-d'),
+ );
+ }
+}
diff --git a/src/Presentation/Api/V1/Dto/Employees/PaginatedEmployee.php b/src/Presentation/Api/V1/Dto/Employees/PaginatedEmployee.php
new file mode 100644
index 0000000..bfa5944
--- /dev/null
+++ b/src/Presentation/Api/V1/Dto/Employees/PaginatedEmployee.php
@@ -0,0 +1,39 @@
+id,
+ firstName: $employee->firstName,
+ lastName: $employee->lastName,
+ establishment: $employee->establishment,
+ site: $employee->site,
+ service: $employee->service,
+ startDate: $employee->startDate->format('Y-m-d'),
+ endDate: $employee->endDate?->format('Y-m-d'),
+ plannedEndDate: $employee->plannedEndDate?->format('Y-m-d'),
+ );
+ }
+}
diff --git a/src/Presentation/Api/V1/Exceptions/ApiErrorCode.php b/src/Presentation/Api/V1/Exceptions/ApiErrorCode.php
new file mode 100644
index 0000000..986883e
--- /dev/null
+++ b/src/Presentation/Api/V1/Exceptions/ApiErrorCode.php
@@ -0,0 +1,28 @@
+ */
+ use BaseEnum;
+
+ case NotFound = 'not-found';
+ case ValidationError = 'validation-error';
+ case BadRequest = 'bad-request';
+ case InternalError = 'internal-error';
+
+ public function title(): string
+ {
+ return match ($this) {
+ self::NotFound => 'Resource Not Found',
+ self::ValidationError => 'Unprocessable Entity',
+ self::BadRequest => 'Bad Request',
+ self::InternalError => 'Internal Server Error',
+ };
+ }
+}
diff --git a/src/Presentation/Api/V1/Exceptions/ApiExceptionRenderer.php b/src/Presentation/Api/V1/Exceptions/ApiExceptionRenderer.php
new file mode 100644
index 0000000..f3e9ac6
--- /dev/null
+++ b/src/Presentation/Api/V1/Exceptions/ApiExceptionRenderer.php
@@ -0,0 +1,74 @@
+toLeagueUri();
+
+ return match (true) {
+ $e instanceof NotFoundException => response()->json([
+ 'type' => (string) $baseUri->withPath('/errors/' . ApiErrorCode::NotFound->value),
+ 'title' => ApiErrorCode::NotFound->title(),
+ 'status' => 404,
+ 'detail' => $e->getMessage(),
+ 'instance' => $request->getPathInfo(),
+ ], 404, ['Content-Type' => self::CONTENT_TYPE]),
+
+ $e instanceof ValidationException => response()->json([
+ 'type' => (string) $baseUri->withPath('/errors/' . ApiErrorCode::ValidationError->value),
+ 'title' => ApiErrorCode::ValidationError->title(),
+ 'status' => 422,
+ 'detail' => $e->getMessage(),
+ 'invalidParams' => array_values(array_map(
+ static function (int | string $field, mixed $messages): array {
+ $reasons = [];
+ if (is_array($messages)) {
+ foreach ($messages as $msg) {
+ if (is_string($msg)) {
+ $reasons[] = $msg;
+ }
+ }
+ }
+
+ return [
+ 'name' => (string) $field,
+ 'reason' => implode(' ', $reasons),
+ ];
+ },
+ array_keys($e->errors()),
+ array_values($e->errors())
+ )),
+ ], 422, ['Content-Type' => self::CONTENT_TYPE]),
+
+ $e instanceof \DomainException => response()->json([
+ 'type' => (string) $baseUri->withPath('/errors/' . ApiErrorCode::BadRequest->value),
+ 'title' => ApiErrorCode::BadRequest->title(),
+ 'status' => 400,
+ 'detail' => $e->getMessage(),
+ 'instance' => $request->getPathInfo(),
+ ], 400, ['Content-Type' => self::CONTENT_TYPE]),
+
+ default => response()->json([
+ 'type' => (string) $baseUri->withPath('/errors/' . ApiErrorCode::InternalError->value),
+ 'title' => ApiErrorCode::InternalError->title(),
+ 'status' => 500,
+ 'detail' => Config::boolean('app.debug') ? $e->getMessage() : 'An unexpected error occurred.',
+ 'instance' => $request->getPathInfo(),
+ ], 500, ['Content-Type' => self::CONTENT_TYPE]),
+ };
+ }
+}
diff --git a/src/Presentation/Api/V1/Http/Controllers/Employees/EmployeeShowController.php b/src/Presentation/Api/V1/Http/Controllers/Employees/EmployeeShowController.php
new file mode 100644
index 0000000..68d4076
--- /dev/null
+++ b/src/Presentation/Api/V1/Http/Controllers/Employees/EmployeeShowController.php
@@ -0,0 +1,36 @@
+ $executor */
+ public function __construct(
+ private FindEmployee $usecase,
+ private UsecaseExecutor $executor,
+ private EmployeeShowPresenter $presenter,
+ ) {
+ }
+
+ public function __invoke(EmployeeShowRequest $request): JsonResponse
+ {
+ /** @var \Application\Usecase\Employees\Find\EmployeeShowView $response */
+ $response = UsecaseBuilder::using($this->executor)
+ ->do($this->usecase)
+ ->from($request->toInput())
+ ->with($this->presenter)
+ ->run();
+
+ return (new EmployeeShowResponse($response))->present();
+ }
+}
diff --git a/src/Presentation/Api/V1/Http/Controllers/Employees/EmployeesIndexController.php b/src/Presentation/Api/V1/Http/Controllers/Employees/EmployeesIndexController.php
new file mode 100644
index 0000000..80e2529
--- /dev/null
+++ b/src/Presentation/Api/V1/Http/Controllers/Employees/EmployeesIndexController.php
@@ -0,0 +1,36 @@
+ $executor */
+ public function __construct(
+ private FindAllEmployees $usecase,
+ private UsecaseExecutor $executor,
+ private EmployeesIndexPresenter $presenter,
+ ) {
+ }
+
+ public function __invoke(EmployeesIndexRequest $request): JsonResponse
+ {
+ /** @var \Application\Usecase\Employees\FindAll\EmployeesIndexView $response */
+ $response = UsecaseBuilder::using($this->executor)
+ ->do($this->usecase)
+ ->from($request->toInput())
+ ->with($this->presenter)
+ ->run();
+
+ return (new EmployeesIndexResponse($response, $request->toLeagueUri()))->present();
+ }
+}
diff --git a/src/Presentation/Api/V1/Http/Requests/Employees/EmployeeShowRequest.php b/src/Presentation/Api/V1/Http/Requests/Employees/EmployeeShowRequest.php
new file mode 100644
index 0000000..a2ab2eb
--- /dev/null
+++ b/src/Presentation/Api/V1/Http/Requests/Employees/EmployeeShowRequest.php
@@ -0,0 +1,39 @@
+> */
+ public function rules(): array
+ {
+ return [
+ 'employeeId' => ['required', 'string', 'regex:/^\d{7,8}$/'],
+ ];
+ }
+
+ public function authorize(): bool
+ {
+ return true;
+ }
+
+ protected function prepareForValidation(): void
+ {
+ $this->merge([
+ 'employeeId' => $this->route('employeeId'),
+ ]);
+ }
+
+ public function toInput(): Input
+ {
+ return new Input(
+ id: new ArcadiaEmployeeId($this->string('employeeId')->value()),
+ );
+ }
+}
diff --git a/src/Presentation/Api/V1/Http/Requests/Employees/EmployeesIndexRequest.php b/src/Presentation/Api/V1/Http/Requests/Employees/EmployeesIndexRequest.php
new file mode 100644
index 0000000..d43fff9
--- /dev/null
+++ b/src/Presentation/Api/V1/Http/Requests/Employees/EmployeesIndexRequest.php
@@ -0,0 +1,82 @@
+> */
+ public function rules(): array
+ {
+ return [
+ 'offset' => ['sometimes', 'integer', 'min:0'],
+ 'limit' => ['sometimes', 'integer', 'min:1', 'max:' . Pagination::MAX_PAGE_SIZE],
+ 'page' => ['sometimes', 'integer', 'min:1'],
+ 'pageSize' => ['sometimes', 'integer', 'min:1', 'max:' . Pagination::MAX_PAGE_SIZE],
+ 'per_page' => ['sometimes', 'integer', 'min:1', 'max:' . Pagination::MAX_PAGE_SIZE],
+ 'sortBy' => ['sometimes', Rule::in(array_map(
+ static fn (EmployeeSortColumn $case): string => $case->name,
+ EmployeeSortColumn::cases()
+ ))],
+ 'sort_by' => ['sometimes', Rule::in(array_map(
+ static fn (EmployeeSortColumn $case): string => $case->name,
+ EmployeeSortColumn::cases()
+ ))],
+ 'sortDirection' => ['sometimes', Rule::in(['Ascending', 'Descending'])],
+ 'direction' => ['sometimes', Rule::in(['Ascending', 'Descending'])],
+ 'since' => ['sometimes', 'date'],
+ 'establishment' => ['sometimes', 'string', 'regex:/^[\dA-Z]{2,}$/'],
+ 'siteId' => ['sometimes', 'string', 'regex:/^[A-Z]{2,}$/'],
+ 'serviceId' => ['sometimes', 'string', 'regex:/^\d{1,}$/'],
+ ];
+ }
+
+ public function authorize(): bool
+ {
+ return true;
+ }
+
+ public function toInput(): Input
+ {
+ return new Input(
+ pagination: $this->pagination(),
+ sorter: new EmployeeSorter($this->sortBy(), $this->direction()),
+ );
+ }
+
+ private function sortBy(): EmployeeSortColumn
+ {
+ $value = $this->string('sortBy')->isEmpty()
+ ? $this->string('sort_by', EmployeeSortColumn::arcadiaId->name)->value()
+ : $this->string('sortBy')->value();
+
+ return match ($value) {
+ 'startDate' => EmployeeSortColumn::startDate,
+ 'endDate' => EmployeeSortColumn::endDate,
+ 'plannedEndDate' => EmployeeSortColumn::plannedEndDate,
+ 'createdAt' => EmployeeSortColumn::createdAt,
+ 'updatedAt' => EmployeeSortColumn::updatedAt,
+ default => EmployeeSortColumn::arcadiaId,
+ };
+ }
+
+ private function direction(): \SortDirection
+ {
+ $value = $this->string('sortDirection')->isEmpty()
+ ? $this->string('direction', \SortDirection::Ascending->name)->value()
+ : $this->string('sortDirection')->value();
+
+ return match ($value) {
+ 'Descending' => \SortDirection::Descending,
+ default => \SortDirection::Ascending,
+ };
+ }
+}
diff --git a/src/Presentation/Api/V1/Http/Responses/Employees/EmployeeShowResponse.php b/src/Presentation/Api/V1/Http/Responses/Employees/EmployeeShowResponse.php
new file mode 100644
index 0000000..64412cb
--- /dev/null
+++ b/src/Presentation/Api/V1/Http/Responses/Employees/EmployeeShowResponse.php
@@ -0,0 +1,28 @@
+view);
+
+ return response()->json([
+ 'employee' => get_object_vars($dto),
+ ]);
+ }
+}
diff --git a/src/Presentation/Api/V1/Http/Responses/Employees/EmployeesIndexResponse.php b/src/Presentation/Api/V1/Http/Responses/Employees/EmployeesIndexResponse.php
new file mode 100644
index 0000000..ac7eafa
--- /dev/null
+++ b/src/Presentation/Api/V1/Http/Responses/Employees/EmployeesIndexResponse.php
@@ -0,0 +1,58 @@
+view->page;
+ $pageSize = $this->view->perPage;
+ $totalItems = $this->view->total;
+ $totalPages = $pageSize > 0 ? (int) ceil($totalItems / $pageSize) : 1;
+
+ $firstUrl = (string) $this->baseUri->withQuery(http_build_query(['page' => 1, 'pageSize' => $pageSize]));
+ $lastUrl = (string) $this->baseUri->withQuery(http_build_query(['page' => $totalPages, 'pageSize' => $pageSize]));
+ $selfUrl = (string) $this->baseUri->withQuery(http_build_query(['page' => $page, 'pageSize' => $pageSize]));
+ $prevUrl = $page > 1 ? (string) $this->baseUri->withQuery(http_build_query(['page' => $page - 1, 'pageSize' => $pageSize])) : null;
+ $nextUrl = $page < $totalPages ? (string) $this->baseUri->withQuery(http_build_query(['page' => $page + 1, 'pageSize' => $pageSize])) : null;
+
+ return response()->json([
+ 'employees' => array_map(
+ static fn (PaginatedEmployee $employee): array => get_object_vars(
+ PaginatedEmployeeDto::fromUsecase($employee)
+ ),
+ $this->view->employees
+ ),
+ 'pagination' => [
+ 'page' => $page,
+ 'pageSize' => $pageSize,
+ 'totalItems' => $totalItems,
+ 'totalPages' => $totalPages,
+ 'links' => [
+ 'self' => $selfUrl,
+ 'first' => $firstUrl,
+ 'prev' => $prevUrl,
+ 'next' => $nextUrl,
+ 'last' => $lastUrl,
+ ],
+ ],
+ ]);
+ }
+}
diff --git a/src/Presentation/Web/Exceptions/WebExceptionRenderer.php b/src/Presentation/Web/Exceptions/WebExceptionRenderer.php
new file mode 100644
index 0000000..f394e2e
--- /dev/null
+++ b/src/Presentation/Web/Exceptions/WebExceptionRenderer.php
@@ -0,0 +1,26 @@
+is('api/*') || $request->wantsJson()) {
+ return null;
+ }
+
+ if ($e instanceof NotFoundException) {
+ return response()->view('index', [], 404);
+ }
+
+ return null;
+ }
+}
diff --git a/src/Presentation/Web/Http/Controllers/ErrorDocumentationController.php b/src/Presentation/Web/Http/Controllers/ErrorDocumentationController.php
new file mode 100644
index 0000000..b1bb1cb
--- /dev/null
+++ b/src/Presentation/Web/Http/Controllers/ErrorDocumentationController.php
@@ -0,0 +1,19 @@
+value, [
+ 'code' => $code,
+ 'title' => $code->title(),
+ ]);
+ }
+}
diff --git a/src/Presentation/Web/Http/Controllers/HomeController.php b/src/Presentation/Web/Http/Controllers/HomeController.php
new file mode 100644
index 0000000..88ae3b2
--- /dev/null
+++ b/src/Presentation/Web/Http/Controllers/HomeController.php
@@ -0,0 +1,15 @@
+Cette erreur indique une violation des règles du domaine métier Arcadia (ex: identifiant invalide ou violation d'invariant métier).
+@endsection
diff --git a/src/Presentation/Web/resources/views/errors/docs/internal-error.blade.php b/src/Presentation/Web/resources/views/errors/docs/internal-error.blade.php
new file mode 100644
index 0000000..15be523
--- /dev/null
+++ b/src/Presentation/Web/resources/views/errors/docs/internal-error.blade.php
@@ -0,0 +1,7 @@
+@extends('errors.docs.layout')
+
+@section('status', '500')
+
+@section('doc-content')
+ Une erreur inattendue est survenue au niveau du serveur. L'incident a été enregistré dans nos journaux système.
+@endsection
diff --git a/src/Presentation/Web/resources/views/errors/docs/layout.blade.php b/src/Presentation/Web/resources/views/errors/docs/layout.blade.php
new file mode 100644
index 0000000..e4cce30
--- /dev/null
+++ b/src/Presentation/Web/resources/views/errors/docs/layout.blade.php
@@ -0,0 +1,25 @@
+@extends('layouts.layout')
+
+@section('title', $title)
+
+@push('styles')
+
+@endpush
+
+@section('content')
+ HTTP @yield('status', '500')
+ {{ $title }} ({{ $code->value }})
+
+ @yield('doc-content')
+
+
+ Conforme à la spécification RFC 7807 Problem Details.
+@endsection
diff --git a/src/Presentation/Web/resources/views/errors/docs/not-found.blade.php b/src/Presentation/Web/resources/views/errors/docs/not-found.blade.php
new file mode 100644
index 0000000..8fc892b
--- /dev/null
+++ b/src/Presentation/Web/resources/views/errors/docs/not-found.blade.php
@@ -0,0 +1,12 @@
+@extends('errors.docs.layout')
+
+@section('status', '404')
+
+@section('doc-content')
+ Cette erreur indique que la ressource demandée n'existe pas ou a été supprimée du système Arcadia.
+ Résolution
+
+ - Vérifiez l'exactitude du matricule ou de l'identifiant transmis dans l'URL.
+ - Consultez l'endpoint de liste pour vérifier les ressources existantes.
+
+@endsection
diff --git a/src/Presentation/Web/resources/views/errors/docs/validation-error.blade.php b/src/Presentation/Web/resources/views/errors/docs/validation-error.blade.php
new file mode 100644
index 0000000..cc40069
--- /dev/null
+++ b/src/Presentation/Web/resources/views/errors/docs/validation-error.blade.php
@@ -0,0 +1,10 @@
+@extends('errors.docs.layout')
+
+@section('status', '422')
+
+@section('doc-content')
+ Cette erreur survient lorsque les données transmises dans la requête HTTP ne satisfont pas les règles de validation du contrat OpenAPI.
+
+ Structure de la réponse
+ Le champ invalidParams contient le détail de chaque champ rejeté et la raison associée.
+@endsection
diff --git a/src/Presentation/Web/resources/views/index.blade.php b/src/Presentation/Web/resources/views/index.blade.php
new file mode 100644
index 0000000..4b625b4
--- /dev/null
+++ b/src/Presentation/Web/resources/views/index.blade.php
@@ -0,0 +1,11 @@
+@extends('layouts.layout')
+
+@section('title', Config::string('app.name'))
+
+@section('content')
+
+
+
{{ Config::string('app.name') }}
+
+
+@endsection
diff --git a/src/Presentation/Web/resources/views/layouts/head.blade.php b/src/Presentation/Web/resources/views/layouts/head.blade.php
new file mode 100644
index 0000000..54ed945
--- /dev/null
+++ b/src/Presentation/Web/resources/views/layouts/head.blade.php
@@ -0,0 +1,29 @@
+{{-- Meta --}}
+
+
+
+
+
+
+@hasSection('canonical')
+
+@else
+
+@endif
+
+{{-- META INDEX, FOLLOW --}}
+@hasSection('metaIndex')
+
+@else
+
+@endif
+
+{{-- Others --}}
+@if (Config::boolean('app.debug'))
+
+@endif
+
+{{-- STYLES --}}
+@stack('styles')
diff --git a/src/Presentation/Web/resources/views/layouts/layout.blade.php b/src/Presentation/Web/resources/views/layouts/layout.blade.php
new file mode 100644
index 0000000..42631b2
--- /dev/null
+++ b/src/Presentation/Web/resources/views/layouts/layout.blade.php
@@ -0,0 +1,21 @@
+
+
+
+
+
+ {{ Config::string('app.name') }} - @yield('title')
+
+ @include('layouts.head')
+
+
+
+
+
+ @yield('content')
+
+
+ @stack('scriptsConstants')
+ @stack('scripts')
+
+
+
diff --git a/src/Shared/DDD/Directory.php b/src/Shared/DDD/Directory.php
new file mode 100644
index 0000000..62c1023
--- /dev/null
+++ b/src/Shared/DDD/Directory.php
@@ -0,0 +1,15 @@
+value;
+ }
+
+ #[\Override]
+ public function equals(mixed $other): bool
+ {
+ return $other instanceof self && $this->value === $other->value;
+ }
+}
diff --git a/src/Shared/DDD/Equatable.php b/src/Shared/DDD/Equatable.php
new file mode 100644
index 0000000..11eaef5
--- /dev/null
+++ b/src/Shared/DDD/Equatable.php
@@ -0,0 +1,10 @@
+ */
+ public function from(Input $input): BuilderStepPresenter;
+}
diff --git a/src/Shared/DDD/Usecase/Builder/BuilderStepPresenter.php b/src/Shared/DDD/Usecase/Builder/BuilderStepPresenter.php
new file mode 100644
index 0000000..ef8728b
--- /dev/null
+++ b/src/Shared/DDD/Usecase/Builder/BuilderStepPresenter.php
@@ -0,0 +1,14 @@
+ $presenter */
+ public function with(Presenter $presenter): BuilderStepBuild;
+}
diff --git a/src/Shared/DDD/Usecase/Builder/BuilderStepUsecase.php b/src/Shared/DDD/Usecase/Builder/BuilderStepUsecase.php
new file mode 100644
index 0000000..ad0cc80
--- /dev/null
+++ b/src/Shared/DDD/Usecase/Builder/BuilderStepUsecase.php
@@ -0,0 +1,17 @@
+ $usecase
+ * @return BuilderStepInput
+ */
+ public function do(Usecase $usecase): BuilderStepInput;
+}
diff --git a/src/Shared/DDD/Usecase/Builder/UsecaseBuilder.php b/src/Shared/DDD/Usecase/Builder/UsecaseBuilder.php
new file mode 100644
index 0000000..835a013
--- /dev/null
+++ b/src/Shared/DDD/Usecase/Builder/UsecaseBuilder.php
@@ -0,0 +1,20 @@
+ $executor
+ * @return BuilderStepUsecase
+ */
+ public static function using(UsecaseExecutor $executor): BuilderStepUsecase
+ {
+ return new UsecaseExecutionBuilder($executor);
+ }
+}
diff --git a/src/Shared/DDD/Usecase/Builder/UsecaseExecutionBuilder.php b/src/Shared/DDD/Usecase/Builder/UsecaseExecutionBuilder.php
new file mode 100644
index 0000000..fb6ca89
--- /dev/null
+++ b/src/Shared/DDD/Usecase/Builder/UsecaseExecutionBuilder.php
@@ -0,0 +1,85 @@
+
+ * @implements BuilderStepPresenter
+ * @implements BuilderStepUsecase
+ */
+final class UsecaseExecutionBuilder implements BuilderStepBuild, BuilderStepInput, BuilderStepPresenter, BuilderStepUsecase
+{
+ /** @param UsecaseExecutor $executor */
+ public function __construct(
+ private readonly UsecaseExecutor $executor,
+ ) {
+ }
+
+ /** @var Usecase|null */
+ private ?Usecase $usecase = null;
+
+ private ?Input $input = null;
+
+ /** @var Presenter|null */
+ private ?Presenter $presenter = null;
+
+ /** @param Usecase $usecase */
+ #[\Override]
+ public function do(Usecase $usecase): BuilderStepInput
+ {
+ $this->usecase = $usecase;
+
+ return $this;
+ }
+
+ #[\Override]
+ public function from(Input $input): BuilderStepPresenter
+ {
+ if ($this->usecase === null) {
+ throw new LogicException('Usecase must be set before input.');
+ }
+
+ $this->input = $input;
+
+ return $this;
+ }
+
+ /** @param Presenter $presenter */
+ #[\Override]
+ public function with(Presenter $presenter): BuilderStepBuild
+ {
+ if ($this->usecase === null || $this->input === null) {
+ throw new LogicException(
+ 'Usecase and input must be set before presenter.'
+ );
+ }
+
+ $this->presenter = $presenter;
+
+ return $this;
+ }
+
+ #[\Override]
+ public function run(): object
+ {
+ if ($this->usecase === null || $this->input === null || $this->presenter === null) {
+ throw new LogicException('Usecase, input and presenter are all required.');
+ }
+
+ return $this->executor->execute(
+ usecase: $this->usecase,
+ input: $this->input,
+ presenter: $this->presenter
+ );
+ }
+}
diff --git a/src/Shared/DDD/Usecase/Builder/UsecaseExecutor.php b/src/Shared/DDD/Usecase/Builder/UsecaseExecutor.php
new file mode 100644
index 0000000..7d797b1
--- /dev/null
+++ b/src/Shared/DDD/Usecase/Builder/UsecaseExecutor.php
@@ -0,0 +1,22 @@
+ $usecase
+ * @param Presenter $presenter
+ */
+ public function execute(Usecase $usecase, Input $input, Presenter $presenter): object;
+}
diff --git a/src/Shared/DDD/Usecase/Executor.php b/src/Shared/DDD/Usecase/Executor.php
new file mode 100644
index 0000000..3d1bb8f
--- /dev/null
+++ b/src/Shared/DDD/Usecase/Executor.php
@@ -0,0 +1,10 @@
+value;
+ }
+
+ public function label(): string
+ {
+ return self::toLabels()[$this->name] ?? ucfirst(strtolower($this->name));
+ }
+
+ public function name(): string
+ {
+ return $this->name;
+ }
+
+ /**
+ * @return array
+ */
+ public static function toLabels(): array
+ {
+ /** @var array|null $cache */
+ static $cache = null;
+
+ if ($cache !== null) {
+ return $cache;
+ }
+
+ $rawLabels = defined(self::class . '::' . self::LABELS_CONSTANT_NAME)
+ ? constant(self::class . '::' . self::LABELS_CONSTANT_NAME)
+ : null;
+
+ /** @var array|null $labels */
+ $labels = is_array($rawLabels) ? $rawLabels : null;
+
+ $result = [];
+ foreach (self::cases() as $enum) {
+ if ($labels !== null && ! isset($labels[$enum->name])) {
+ throw new \Error('Missing definition label ' . self::class . " for '{$enum->name}'");
+ }
+ $result[$enum->name] = isset($labels[$enum->name]) ? (string) $labels[$enum->name] : ucfirst(strtolower($enum->name));
+ }
+
+ return $cache = $result;
+ }
+
+ /**
+ * @return array
+ */
+ public static function toValues(): array
+ {
+ /** @var array|null $cache */
+ static $cache = null;
+
+ if ($cache !== null) {
+ return $cache;
+ }
+
+ /** @var array $result */
+ $result = array_column(
+ self::cases(),
+ 'value',
+ 'name'
+ );
+
+ return $cache = $result;
+ }
+
+ /**
+ * @param self|V $value
+ */
+ public static function make(self | int | string $value, string $field = 'value'): ?self
+ {
+ if ($value instanceof self) {
+ return $value;
+ }
+
+ if ($field === 'value') {
+ $tryValue = null;
+ try {
+ $tryValue = self::tryFrom(intval($value));
+ } catch (\ValueError) {
+ $tryValue = self::tryFrom(strval($value));
+ } finally {
+ if ($tryValue !== null) {
+ return $tryValue;
+ }
+ }
+ }
+
+ if ($field === 'label') {
+ $normalizedSearch = preg_replace('/[\W_]+/u', '', mb_strtolower((string) $value));
+
+ foreach (self::cases() as $enum) {
+ $normalizedLabel = preg_replace('/[\W_]+/u', '', mb_strtolower($enum->label()));
+ if ($normalizedLabel === $normalizedSearch) {
+ return $enum;
+ }
+ }
+
+ return null;
+ }
+
+ foreach (self::cases() as $enum) {
+ if ($enum->{$field} === $value) {
+ return $enum;
+ }
+ }
+
+ return null;
+ }
+
+ public function equals(object ...$others): bool
+ {
+ return in_array($this, $others, true);
+ }
+
+ public function jsonSerialize(): mixed
+ {
+ return $this->value;
+ }
+
+ // * PRIVATE
+
+ /**
+ * @return array>
+ */
+ private static function getCustomDefinitions(): array
+ {
+ /** @var array>|null $cache */
+ static $cache = null;
+
+ if ($cache !== null) {
+ return $cache;
+ }
+
+ $names = array_column(self::cases(), 'name', 'name');
+ /** @var array> $filteredConstants */
+ $filteredConstants = [];
+
+ foreach ((new \ReflectionClass(self::class))->getConstants() as $key => $constant) {
+ if ($key === self::LABELS_CONSTANT_NAME || ! \is_array($constant)) {
+ continue;
+ }
+
+ /** @var array $constant */
+ if (! empty(array_intersect_key($constant, $names))) {
+ $filteredConstants[$key] = $constant;
+ }
+ }
+
+ return $cache = $filteredConstants;
+ }
+}
diff --git a/src/Shared/Helpers/DatesHelper.php b/src/Shared/Helpers/DatesHelper.php
new file mode 100644
index 0000000..b8035b6
--- /dev/null
+++ b/src/Shared/Helpers/DatesHelper.php
@@ -0,0 +1,119 @@
+ $now->between($from, $to),
+ $from !== null => $now->greaterThanOrEqualTo($from),
+ $to !== null => $now->lessThanOrEqualTo($to),
+ default => false,
+ };
+ }
+
+ public static function toRfc3339(\DateTimeInterface | string $datetime): string
+ {
+ $datetime = is_string($datetime) ? self::parseDateTime($datetime) : $datetime;
+
+ return $datetime->format(\DATE_RFC3339);
+ }
+
+ public static function parseDateTime(string $datetime): \DateTimeInterface
+ {
+ $datetime = trim($datetime);
+
+ /** @var \DateTimeInterface|null */
+ $output = null;
+
+ switch (true) {
+ case (bool) preg_match(self::FRENCH_DATE_REGEX, $datetime):
+ $output = self::parseFrench($datetime);
+ break;
+ case (bool) preg_match(self::FRENCH_DATE_INVERT_REGEX, $datetime):
+ $output = self::parseFrenchInverted($datetime);
+ break;
+ case (bool) preg_match(self::RFC3339_REGEX, $datetime):
+ $output = self::parseRfc3339($datetime);
+ break;
+ case (bool) preg_match(self::ISO8601_REGEX, $datetime):
+ $output = self::parseIso8601($datetime);
+ break;
+ default:
+ try {
+ $output = new \DateTimeImmutable($datetime);
+ } catch (\Exception) {
+ throw new \InvalidArgumentException('Unrecognized date/time format: ' . $datetime);
+ }
+ }
+
+ return $output;
+ }
+
+ protected static function parseFrench(string $datetime): \DateTimeInterface
+ {
+ $dt = \DateTimeImmutable::createFromFormat('Y-m-d H:i:s', $datetime . ' 00:00:00');
+
+ return $dt ?: self::parseFallback($datetime);
+ }
+
+ protected static function parseFrenchInverted(string $datetime): \DateTimeInterface
+ {
+ $dt = \DateTimeImmutable::createFromFormat('d-m-Y H:i:s', $datetime . ' 00:00:00');
+
+ return $dt ?: self::parseFallback($datetime);
+ }
+
+ protected static function parseRfc3339(string $datetime): \DateTimeInterface
+ {
+ $dt = \DateTimeImmutable::createFromFormat(\DateTime::RFC3339, $datetime);
+ if ($dt !== false) {
+ return $dt;
+ }
+
+ $dt = \DateTimeImmutable::createFromFormat('Y-m-d\TH:i:s.uP', $datetime);
+
+ return $dt ?: self::parseFallback($datetime);
+ }
+
+ protected static function parseIso8601(string $datetime): \DateTimeInterface
+ {
+ $dt = \DateTimeImmutable::createFromFormat(\DateTimeInterface::ATOM, $datetime);
+
+ return $dt ?: self::parseFallback($datetime);
+ }
+
+ protected static function parseFallback(string $datetime): \DateTimeInterface
+ {
+ try {
+ return new \DateTimeImmutable($datetime);
+ } catch (\Throwable) {
+ throw new \InvalidArgumentException("Unrecognized date/time format: {$datetime}");
+ }
+ }
+}
diff --git a/src/Shared/Helpers/UuidHelper.php b/src/Shared/Helpers/UuidHelper.php
new file mode 100644
index 0000000..2a5cb4c
--- /dev/null
+++ b/src/Shared/Helpers/UuidHelper.php
@@ -0,0 +1,47 @@
+getFields();
+
+ if ($fields instanceof Rfc4122FieldsInterface) {
+ $version = $fields->getVersion();
+
+ if ($version !== null) {
+ return $version;
+ }
+ }
+
+ $uuidString = $uuid->toString();
+
+ if (strlen($uuidString) >= 15) {
+ return (int) hexdec($uuidString[14]);
+ }
+
+ return 0;
+ }
+}
diff --git a/src/Shared/Paginated.php b/src/Shared/Paginated.php
new file mode 100644
index 0000000..714f47c
--- /dev/null
+++ b/src/Shared/Paginated.php
@@ -0,0 +1,40 @@
+items as $item) {
+ /** @var T $item */
+ $items[] = clone $item;
+ }
+
+ return $items;
+ }
+
+ public function getPagination(): Pagination
+ {
+ return $this->pagination;
+ }
+
+ public function getTotal(): int
+ {
+ return $this->total;
+ }
+}
diff --git a/src/Shared/Pagination.php b/src/Shared/Pagination.php
new file mode 100644
index 0000000..8f0ad77
--- /dev/null
+++ b/src/Shared/Pagination.php
@@ -0,0 +1,97 @@
+ self::MAX_PAGE_SIZE) {
+ throw new \InvalidArgumentException('Page size must be less than or equal to ' . self::MAX_PAGE_SIZE);
+ }
+ }
+
+ public function from(): int
+ {
+ return $this->from;
+ }
+
+ public function to(): int
+ {
+ return $this->to;
+ }
+
+ public function pageSize(): int
+ {
+ return $this->to - $this->from + 1;
+ }
+
+ public function pageNumber(): int
+ {
+ return (int) ($this->from / $this->pageSize()) + 1;
+ }
+
+ public static function ofIndexes(int $from, int $to): self
+ {
+ return new self($from, $to);
+ }
+
+ public static function ofPage(int $pageNumber, int $pageSize): self
+ {
+ if ($pageNumber <= 0) {
+ throw new \InvalidArgumentException('Page number must be positive and non-zero');
+ }
+ if ($pageSize <= 0) {
+ throw new \InvalidArgumentException('Page size must be positive and non-zero');
+ }
+
+ $fromIndex = ($pageNumber - 1) * $pageSize;
+ $toIndex = max($pageNumber * $pageSize - 1, 1);
+
+ return new self($fromIndex, $toIndex);
+ }
+
+ public static function ofOffsetAndLimit(int $offset, int $limit): self
+ {
+ if ($offset < 0) {
+ throw new \InvalidArgumentException('Offset must be non-negative');
+ }
+ if ($limit <= 0) {
+ throw new \InvalidArgumentException('Limit must be positive and non-zero');
+ }
+
+ $fromIndex = $offset;
+ $toIndex = max($offset + $limit - 1, 1);
+
+ return new self($fromIndex, $toIndex);
+ }
+
+ public static function firstPage(int $pageSize = 25): self
+ {
+ return self::ofPage(1, $pageSize);
+ }
+
+ public function __toString(): string
+ {
+ return sprintf('Pagination{from=%d, to=%d}', $this->from, $this->to);
+ }
+}
diff --git a/storage/app/.gitignore b/storage/app/.gitignore
new file mode 100644
index 0000000..fedb287
--- /dev/null
+++ b/storage/app/.gitignore
@@ -0,0 +1,4 @@
+*
+!private/
+!public/
+!.gitignore
diff --git a/storage/app/private/.gitignore b/storage/app/private/.gitignore
new file mode 100644
index 0000000..d6b7ef3
--- /dev/null
+++ b/storage/app/private/.gitignore
@@ -0,0 +1,2 @@
+*
+!.gitignore
diff --git a/storage/app/public/.gitignore b/storage/app/public/.gitignore
new file mode 100644
index 0000000..d6b7ef3
--- /dev/null
+++ b/storage/app/public/.gitignore
@@ -0,0 +1,2 @@
+*
+!.gitignore
diff --git a/storage/framework/.gitignore b/storage/framework/.gitignore
new file mode 100644
index 0000000..05c4471
--- /dev/null
+++ b/storage/framework/.gitignore
@@ -0,0 +1,9 @@
+compiled.php
+config.php
+down
+events.scanned.php
+maintenance.php
+routes.php
+routes.scanned.php
+schedule-*
+services.json
diff --git a/storage/framework/cache/.gitignore b/storage/framework/cache/.gitignore
new file mode 100644
index 0000000..01e4a6c
--- /dev/null
+++ b/storage/framework/cache/.gitignore
@@ -0,0 +1,3 @@
+*
+!data/
+!.gitignore
diff --git a/storage/framework/cache/data/.gitignore b/storage/framework/cache/data/.gitignore
new file mode 100644
index 0000000..d6b7ef3
--- /dev/null
+++ b/storage/framework/cache/data/.gitignore
@@ -0,0 +1,2 @@
+*
+!.gitignore
diff --git a/storage/framework/sessions/.gitignore b/storage/framework/sessions/.gitignore
new file mode 100644
index 0000000..d6b7ef3
--- /dev/null
+++ b/storage/framework/sessions/.gitignore
@@ -0,0 +1,2 @@
+*
+!.gitignore
diff --git a/storage/framework/testing/.gitignore b/storage/framework/testing/.gitignore
new file mode 100644
index 0000000..d6b7ef3
--- /dev/null
+++ b/storage/framework/testing/.gitignore
@@ -0,0 +1,2 @@
+*
+!.gitignore
diff --git a/storage/framework/views/.gitignore b/storage/framework/views/.gitignore
new file mode 100644
index 0000000..d6b7ef3
--- /dev/null
+++ b/storage/framework/views/.gitignore
@@ -0,0 +1,2 @@
+*
+!.gitignore
diff --git a/storage/logs/.gitignore b/storage/logs/.gitignore
new file mode 100644
index 0000000..d6b7ef3
--- /dev/null
+++ b/storage/logs/.gitignore
@@ -0,0 +1,2 @@
+*
+!.gitignore
diff --git a/tests/Architecture/ApplicationTest.php b/tests/Architecture/ApplicationTest.php
new file mode 100644
index 0000000..fe69821
--- /dev/null
+++ b/tests/Architecture/ApplicationTest.php
@@ -0,0 +1,27 @@
+expect('Application')
+ ->not->toUse([
+ 'Presentation',
+ 'Infra',
+ 'Infrastructure',
+ 'App',
+ ]);
+
+ arch('Application layer does not depend on Illuminate framework')
+ ->expect('Application')
+ ->not->toUse('Illuminate');
+
+ arch('Application layer uses strict types')
+ ->expect('Application')
+ ->toUseStrictTypes();
+
+ arch('Application Usecase classes are final and readonly')
+ ->expect('Application\Usecase')
+ ->toBeReadonly()
+ ->toBeFinal();
+});
diff --git a/tests/Architecture/CodingStandardsTest.php b/tests/Architecture/CodingStandardsTest.php
new file mode 100644
index 0000000..a6b3e92
--- /dev/null
+++ b/tests/Architecture/CodingStandardsTest.php
@@ -0,0 +1,57 @@
+preset()->php();
+ // assert(bool) est intentionnel pour le type narrowing PHPStan, seul assert(string) est dangereux (deprecated PHP 8.3)
+ arch()->preset()->security()->ignoring('assert');
+
+ arch('config() helper is not used in src (use Config facade instead)')
+ ->expect('config')
+ ->not->toBeUsed();
+
+ arch('env() helper is not used in src (use Config facade instead)')
+ ->expect('env')
+ ->not->toBeUsed();
+
+ arch('debug functions are not used in src')
+ ->expect(['dd', 'dump', 'var_dump', 'die', 'print_r', 'ray'])
+ ->not->toBeUsed();
+
+ arch('shell execution functions are not used in src')
+ ->expect(['exec', 'shell_exec', 'system', 'passthru', 'proc_open'])
+ ->not->toBeUsed();
+
+ arch('eval function is not used in src')
+ ->expect('eval')
+ ->not->toBeUsed();
+
+ arch('insecure hashing functions are not used in src')
+ ->expect(['md5', 'sha1'])
+ ->not->toBeUsed();
+
+ arch('sleep functions are not used in src')
+ ->expect(['sleep', 'usleep'])
+ ->not->toBeUsed();
+
+ arch('all Domain source files use strict types')
+ ->expect('Domain')
+ ->toUseStrictTypes();
+
+ arch('all Application source files use strict types')
+ ->expect('Application')
+ ->toUseStrictTypes();
+
+ arch('all Presentation source files use strict types')
+ ->expect('Presentation')
+ ->toUseStrictTypes();
+
+ arch('all Infra source files use strict types')
+ ->expect('Infra')
+ ->toUseStrictTypes();
+
+ arch('all Shared source files use strict types')
+ ->expect('Shared')
+ ->toUseStrictTypes();
+});
diff --git a/tests/Architecture/DomainTest.php b/tests/Architecture/DomainTest.php
new file mode 100644
index 0000000..7089882
--- /dev/null
+++ b/tests/Architecture/DomainTest.php
@@ -0,0 +1,97 @@
+expect('Domain\Models\Entities')
+ ->toImplement(Entity::class);
+
+ arch('Domain Entities are final and readonly')
+ ->expect('Domain\Models\Entities')
+ ->toBeReadonly()
+ ->toBeFinal();
+
+ arch('Domain Ports contain only interfaces')
+ ->expect('Domain\Ports')
+ ->classes()
+ ->toBeInterface();
+
+ arch('Domain Port Directories extend Shared\DDD\Directory')
+ ->expect('Domain\Ports\Directories')
+ ->toExtend(Directory::class);
+
+ arch('Domain Port Repositories extend Shared\DDD\Repository')
+ ->expect('Domain\Ports\Repositories')
+ ->toExtend(Repository::class);
+
+ arch('Domain does not depend on Application, Presentation, Infra, or App')
+ ->expect('Domain')
+ ->not->toUse([
+ 'Application',
+ 'Presentation',
+ 'Infra',
+ 'Infrastructure',
+ 'App',
+ ]);
+
+ arch('Domain does not depend on Illuminate or Symfony frameworks')
+ ->expect('Domain')
+ ->not->toUse([
+ 'Illuminate',
+ 'Symfony',
+ ]);
+
+ arch('Domain Value Objects are readonly')
+ ->expect('Domain\Models\ValueObjects')
+ ->toBeReadonly()
+ ->ignoring([
+ 'Domain\Models\ValueObjects\Employees\EmployeeSortColumn',
+ 'Domain\Models\ValueObjects\Inco\PortionType',
+ 'Domain\Models\ValueObjects\IncoCompo\IncoCompoPartDto',
+ ]);
+
+ arch('Domain exceptions extend native DomainException')
+ ->expect('Domain\Exceptions')
+ ->toExtend(\DomainException::class);
+
+ arch('Domain does not use Laravel helper functions')
+ ->expect('Domain')
+ ->not->toUse([
+ 'abort',
+ 'app',
+ 'auth',
+ 'asset',
+ 'back',
+ 'bcrypt',
+ 'broadcast',
+ 'cache',
+ 'config',
+ 'cookie',
+ 'csrf_token',
+ 'dd',
+ 'dump',
+ 'decrypt',
+ 'dispatch',
+ 'event',
+ 'factory',
+ 'logger',
+ 'redirect',
+ 'request',
+ 'response',
+ 'route',
+ 'session',
+ 'storage',
+ 'url',
+ 'throw_if',
+ 'throw_unless',
+ '__',
+ 'trans',
+ 'trans_choice',
+ 'view',
+ ]);
+});
diff --git a/tests/Architecture/InfraTest.php b/tests/Architecture/InfraTest.php
new file mode 100644
index 0000000..664067b
--- /dev/null
+++ b/tests/Architecture/InfraTest.php
@@ -0,0 +1,31 @@
+expect('Infra')
+ ->not->toUse('App');
+
+ arch('Infra Eloquent Database Models extend Eloquent Model')
+ ->expect('Infra\Database\Models')
+ ->toExtend(Model::class);
+
+ arch('Infra Eloquent Database Models are final')
+ ->expect('Infra\Database\Models')
+ ->toBeFinal();
+
+ arch('Infra adapters implement Domain Ports')
+ ->expect('Infra\Adapters\Directories\EloquentEmployeeDirectory')
+ ->toImplement('Domain\Ports\Directories\EmployeeDirectory');
+
+ arch('Infra EloquentEmployeeRepository implements Domain EmployeeRepository port')
+ ->expect('Infra\Adapters\Repositories\EloquentEmployeeRepository')
+ ->toImplement('Domain\Ports\Repositories\EmployeeRepository');
+
+ arch('Infra layer uses strict types')
+ ->expect('Infra')
+ ->toUseStrictTypes();
+});
diff --git a/tests/Architecture/NamingConventionsTest.php b/tests/Architecture/NamingConventionsTest.php
new file mode 100644
index 0000000..67edb8a
--- /dev/null
+++ b/tests/Architecture/NamingConventionsTest.php
@@ -0,0 +1,47 @@
+expect('Application\Usecase')
+ ->toUseStrictTypes();
+});
+
+describe('Naming Conventions in Domain', function (): void {
+ arch('Port Directories have Directory suffix')
+ ->expect('Domain\Ports\Directories')
+ ->toHaveSuffix('Directory');
+
+ arch('Port Repositories have Repository suffix')
+ ->expect('Domain\Ports\Repositories')
+ ->toHaveSuffix('Repository');
+});
+
+describe('Naming Conventions in Presentation', function (): void {
+ arch('Controllers have Controller suffix')
+ ->expect('Presentation\Api\V1\Http\Controllers')
+ ->toHaveSuffix('Controller');
+
+ arch('Requests have Request suffix')
+ ->expect('Presentation\Api\V1\Http\Requests')
+ ->toHaveSuffix('Request');
+
+ arch('Responses have Response suffix')
+ ->expect('Presentation\Api\V1\Http\Responses')
+ ->toHaveSuffix('Response');
+});
+
+describe('Naming Conventions in Infra', function (): void {
+ arch('Infra service providers have Provider suffix')
+ ->expect('Infra\Providers')
+ ->toHaveSuffix('Provider');
+
+ arch('Infra directory adapters have Directory suffix')
+ ->expect('Infra\Adapters\Directories')
+ ->toHaveSuffix('Directory');
+
+ arch('Infra repository adapters have Repository suffix')
+ ->expect('Infra\Adapters\Repositories')
+ ->toHaveSuffix('Repository');
+});
diff --git a/tests/Architecture/PresentationTest.php b/tests/Architecture/PresentationTest.php
new file mode 100644
index 0000000..b5b09d5
--- /dev/null
+++ b/tests/Architecture/PresentationTest.php
@@ -0,0 +1,31 @@
+expect('Presentation')
+ ->not->toUse([
+ 'Infra',
+ 'Infrastructure',
+ 'App',
+ ]);
+
+ arch('Presentation Controllers are invokable single action controllers')
+ ->expect('Presentation\Api\V1\Http\Controllers')
+ ->toBeInvokable();
+
+ arch('Presentation Responses implement Presentation\Api\V1\Contracts\ApiResponse')
+ ->expect('Presentation\Api\V1\Http\Responses')
+ ->toImplement(ApiResponse::class);
+
+ arch('Presentation FormRequests extend Illuminate\Foundation\Http\FormRequest')
+ ->expect('Presentation\Api\V1\Http\Requests')
+ ->toExtend('Illuminate\Foundation\Http\FormRequest');
+
+ arch('Presentation layer uses strict types')
+ ->expect('Presentation')
+ ->toUseStrictTypes();
+});
diff --git a/tests/CreatesApplication.php b/tests/CreatesApplication.php
new file mode 100644
index 0000000..99e5be9
--- /dev/null
+++ b/tests/CreatesApplication.php
@@ -0,0 +1,25 @@
+make(Kernel::class)->bootstrap();
+
+ return $app;
+ }
+}
diff --git a/tests/Feature/ErrorDocumentationTest.php b/tests/Feature/ErrorDocumentationTest.php
new file mode 100644
index 0000000..cb3e6ba
--- /dev/null
+++ b/tests/Feature/ErrorDocumentationTest.php
@@ -0,0 +1,37 @@
+get("/errors/{$code->value}");
+
+ // THEN
+ $response->assertStatus(200);
+ $response->assertSee('Resource Not Found');
+ $response->assertSee('not-found');
+ });
+
+ it('returns a 404 for an invalid error code slug', function (): void {
+ // GIVEN
+ /** @var \Tests\TestCase $test */
+ $test = $this;
+ $invalidSlug = 'non-existing-error-code';
+
+ // WHEN
+ $response = $test->get("/errors/{$invalidSlug}");
+
+ // THEN
+ $response->assertStatus(404);
+ });
+});
diff --git a/tests/Feature/ExampleTest.php b/tests/Feature/ExampleTest.php
new file mode 100644
index 0000000..022deba
--- /dev/null
+++ b/tests/Feature/ExampleTest.php
@@ -0,0 +1,19 @@
+get('/');
+
+ // THEN
+ $response->assertStatus(200);
+ });
+});
diff --git a/tests/Feature/OpenApiConformanceTest.php b/tests/Feature/OpenApiConformanceTest.php
new file mode 100644
index 0000000..e27f277
--- /dev/null
+++ b/tests/Feature/OpenApiConformanceTest.php
@@ -0,0 +1,95 @@
+create([
+ 'public_employee_number' => '0115590',
+ 'last_name' => 'DOE',
+ 'first_name' => 'John',
+ 'start_date' => '2024-01-15',
+ 'establishment' => '01',
+ 'site' => 'LDCSER',
+ 'service' => '097',
+ ]);
+
+ // WHEN
+ /** @var \Illuminate\Testing\TestResponse<\Symfony\Component\HttpFoundation\Response> $response */
+ $response = $test->getJson('/api/v1/employees');
+
+ // THEN
+ $response->assertStatus(200);
+ $response->assertValidRequest();
+ $response->assertValidResponse(200);
+ });
+
+ it('validates GET /api/v1/employees/{id} detail response against openapi spec', function (): void {
+ // GIVEN
+ /** @var \Tests\TestCase $test */
+ $test = $this;
+
+ Employee::factory()->create([
+ 'public_employee_number' => '0115591',
+ 'last_name' => 'SMITH',
+ 'first_name' => 'Jane',
+ 'start_date' => '2024-02-01',
+ 'establishment' => '02',
+ 'site' => 'SLELA',
+ 'service' => '098',
+ ]);
+
+ // WHEN
+ /** @var \Illuminate\Testing\TestResponse<\Symfony\Component\HttpFoundation\Response> $response */
+ $response = $test->getJson('/api/v1/employees/0115591');
+
+ // THEN
+ $response->assertValidRequest();
+ $response->assertValidResponse(200);
+ });
+
+ it('validates GET /api/v1/employees/{id} not found response against openapi spec', function (): void {
+ // GIVEN
+ /** @var \Tests\TestCase $test */
+ $test = $this;
+ $unexistingId = '9999999';
+
+ // WHEN
+ /** @var \Illuminate\Testing\TestResponse<\Symfony\Component\HttpFoundation\Response> $response */
+ $response = $test->getJson("/api/v1/employees/{$unexistingId}");
+
+ // THEN
+ $response->assertValidRequest();
+ $response->assertValidResponse(404);
+ });
+
+ it('validates GET /api/v1/employees/{id} validation error for invalid matricule', function (): void {
+ // GIVEN
+ /** @var \Tests\TestCase $test */
+ $test = $this;
+ $invalidId = 'invalid';
+
+ // WHEN
+ /** @var \Illuminate\Testing\TestResponse<\Symfony\Component\HttpFoundation\Response> $response */
+ $response = $test->getJson("/api/v1/employees/{$invalidId}");
+
+ // THEN
+ $response->assertStatus(422);
+ $response->assertValidResponse(422);
+ });
+});
diff --git a/tests/Pest.php b/tests/Pest.php
new file mode 100644
index 0000000..b982987
--- /dev/null
+++ b/tests/Pest.php
@@ -0,0 +1,39 @@
+extend(LaravelTestCase::class)
+ ->use(RefreshDatabase::class)
+ ->beforeEach(function (): void {
+ Http::preventStrayRequests();
+ })
+ ->in('Feature');
+
+pest()
+ ->extend(LaravelTestCase::class)
+ ->use(RefreshDatabase::class)
+ ->in('Integration/WithApp');
+
+pest()
+ ->extend(BasePHPUnitTestCase::class)
+ ->in('Integration/Standalones');
+
+pest()
+ ->extend(BasePHPUnitTestCase::class)
+ ->in('Unit');
+pest()->extend(LaravelTestCase::class)->in('Unit/App/Casts');
diff --git a/tests/TestCase.php b/tests/TestCase.php
new file mode 100644
index 0000000..6358e31
--- /dev/null
+++ b/tests/TestCase.php
@@ -0,0 +1,14 @@
+value)
+ ->toBe('0115590')
+ ->and((string) $employeeId)->toBe('0115590');
+ });
+
+ it('instantiates successfully with a valid 8-digit matricule', function (): void {
+ // GIVEN
+ $validMatricule = '01155902';
+
+ // WHEN
+ $employeeId = new ArcadiaEmployeeId($validMatricule);
+
+ // THEN
+ expect($employeeId->value)
+ ->toBe('01155902')
+ ->and((string) $employeeId)->toBe('01155902');
+ });
+
+ it('throws a DomainException when given an invalid matricule pattern', function (): void {
+ // GIVEN
+ $invalidMatricule = '12345';
+
+ // WHEN & THEN
+ expect(fn () => new ArcadiaEmployeeId($invalidMatricule))
+ ->toThrow(\DomainException::class);
+ });
+
+ it('supports equality check with another ArcadiaEmployeeId instance', function (): void {
+ // GIVEN
+ $firstId = new ArcadiaEmployeeId('01155902');
+ $sameId = new ArcadiaEmployeeId('01155902');
+ $differentId = new ArcadiaEmployeeId('01155901');
+
+ // WHEN & THEN
+ expect($firstId->equals($sameId))
+ ->toBeTrue()
+ ->and($firstId->equals($differentId))
+ ->toBeFalse();
+ });
+});
diff --git a/tests/Unit/ExampleTest.php b/tests/Unit/ExampleTest.php
new file mode 100644
index 0000000..5024bf5
--- /dev/null
+++ b/tests/Unit/ExampleTest.php
@@ -0,0 +1,19 @@
+toBe(5);
+ });
+});