diff --git a/composer.json b/composer.json index 141548d5..9c388154 100644 --- a/composer.json +++ b/composer.json @@ -21,6 +21,7 @@ "require": { "php": "~8.1.0 || ~8.2.0 || ~8.3.0", "doctrine/dbal": "^3.8.1|^4.0.0", + "doctrine/migrations": "^3.3.2", "patchlevel/hydrator": "^1.1.0", "patchlevel/worker": "^1.1.1", "psr/cache": "^2.0.0|^3.0.0", @@ -35,7 +36,6 @@ "require-dev": { "ext-pdo_sqlite": "~8.1.0 || ~8.2.0 || ~8.3.0", "cspray/phinal": "^2.0.0", - "doctrine/migrations": "^3.3.2", "doctrine/orm": "^2.18.0|^3.0.0", "infection/infection": "^0.27.0", "patchlevel/coding-standard": "^1.3.0", @@ -51,11 +51,7 @@ "vimeo/psalm": "^5.17.0" }, "suggest": { - "doctrine/migrations": "for schema migration support", - "symfony/messenger": "for an advanced event bus" - }, - "conflict": { - "doctrine/migrations": "<3.3" + "patchlevel/event-sourcing-psalm-plugin": "for psalm support" }, "config": { "preferred-install": { diff --git a/composer.lock b/composer.lock index 1c838165..98522e43 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "a224315131e5bcf3d55ab4f82052c52a", + "content-hash": "06b66664b0ad72a735e5a54f0722966e", "packages": [ { "name": "brick/math", @@ -216,6 +216,199 @@ }, "time": "2024-01-30T19:34:25+00:00" }, + { + "name": "doctrine/event-manager", + "version": "2.0.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/event-manager.git", + "reference": "750671534e0241a7c50ea5b43f67e23eb5c96f32" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/event-manager/zipball/750671534e0241a7c50ea5b43f67e23eb5c96f32", + "reference": "750671534e0241a7c50ea5b43f67e23eb5c96f32", + "shasum": "" + }, + "require": { + "php": "^8.1" + }, + "conflict": { + "doctrine/common": "<2.9" + }, + "require-dev": { + "doctrine/coding-standard": "^10", + "phpstan/phpstan": "^1.8.8", + "phpunit/phpunit": "^9.5", + "vimeo/psalm": "^4.28" + }, + "type": "library", + "autoload": { + "psr-4": { + "Doctrine\\Common\\": "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" + }, + { + "name": "Marco Pivetta", + "email": "ocramius@gmail.com" + } + ], + "description": "The Doctrine Event Manager is a simple PHP event system that was built to be used with the various Doctrine projects.", + "homepage": "https://www.doctrine-project.org/projects/event-manager.html", + "keywords": [ + "event", + "event dispatcher", + "event manager", + "event system", + "events" + ], + "support": { + "issues": "https://github.com/doctrine/event-manager/issues", + "source": "https://github.com/doctrine/event-manager/tree/2.0.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%2Fevent-manager", + "type": "tidelift" + } + ], + "time": "2022-10-12T20:59:15+00:00" + }, + { + "name": "doctrine/migrations", + "version": "3.7.2", + "source": { + "type": "git", + "url": "https://github.com/doctrine/migrations.git", + "reference": "47af29eef49f29ebee545947e8b2a4b3be318c8a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/migrations/zipball/47af29eef49f29ebee545947e8b2a4b3be318c8a", + "reference": "47af29eef49f29ebee545947e8b2a4b3be318c8a", + "shasum": "" + }, + "require": { + "composer-runtime-api": "^2", + "doctrine/dbal": "^3.5.1 || ^4", + "doctrine/deprecations": "^0.5.3 || ^1", + "doctrine/event-manager": "^1.2 || ^2.0", + "php": "^8.1", + "psr/log": "^1.1.3 || ^2 || ^3", + "symfony/console": "^5.4 || ^6.0 || ^7.0", + "symfony/stopwatch": "^5.4 || ^6.0 || ^7.0", + "symfony/var-exporter": "^6.2 || ^7.0" + }, + "conflict": { + "doctrine/orm": "<2.12 || >=4" + }, + "require-dev": { + "doctrine/coding-standard": "^12", + "doctrine/orm": "^2.13 || ^3", + "doctrine/persistence": "^2 || ^3", + "doctrine/sql-formatter": "^1.0", + "ext-pdo_sqlite": "*", + "phpstan/phpstan": "^1.10", + "phpstan/phpstan-deprecation-rules": "^1.1", + "phpstan/phpstan-phpunit": "^1.3", + "phpstan/phpstan-strict-rules": "^1.4", + "phpstan/phpstan-symfony": "^1.3", + "phpunit/phpunit": "^10.3", + "symfony/cache": "^5.4 || ^6.0 || ^7.0", + "symfony/process": "^5.4 || ^6.0 || ^7.0", + "symfony/yaml": "^5.4 || ^6.0 || ^7.0" + }, + "suggest": { + "doctrine/sql-formatter": "Allows to generate formatted SQL with the diff command.", + "symfony/yaml": "Allows the use of yaml for migration configuration files." + }, + "bin": [ + "bin/doctrine-migrations" + ], + "type": "library", + "autoload": { + "psr-4": { + "Doctrine\\Migrations\\": "lib/Doctrine/Migrations" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Michael Simonson", + "email": "contact@mikesimonson.com" + } + ], + "description": "PHP Doctrine Migrations project offer additional functionality on top of the database abstraction layer (DBAL) for versioning your database schema and easily deploying changes to it. It is a very easy to use and a powerful tool.", + "homepage": "https://www.doctrine-project.org/projects/migrations.html", + "keywords": [ + "database", + "dbal", + "migrations" + ], + "support": { + "issues": "https://github.com/doctrine/migrations/issues", + "source": "https://github.com/doctrine/migrations/tree/3.7.2" + }, + "funding": [ + { + "url": "https://www.doctrine-project.org/sponsorship.html", + "type": "custom" + }, + { + "url": "https://www.patreon.com/phpdoctrine", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/doctrine%2Fmigrations", + "type": "tidelift" + } + ], + "time": "2023-12-05T11:35:05+00:00" + }, { "name": "patchlevel/hydrator", "version": "1.1.0", @@ -1538,6 +1731,68 @@ ], "time": "2023-12-26T14:02:43+00:00" }, + { + "name": "symfony/stopwatch", + "version": "v7.0.3", + "source": { + "type": "git", + "url": "https://github.com/symfony/stopwatch.git", + "reference": "983900d6fddf2b0cbaacacbbad07610854bd8112" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/stopwatch/zipball/983900d6fddf2b0cbaacacbbad07610854bd8112", + "reference": "983900d6fddf2b0cbaacacbbad07610854bd8112", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "symfony/service-contracts": "^2.5|^3" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Stopwatch\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides a way to profile code", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/stopwatch/tree/v7.0.3" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-01-23T15:02:46+00:00" + }, { "name": "symfony/string", "version": "v7.0.3", @@ -1623,6 +1878,80 @@ } ], "time": "2024-01-29T15:41:16+00:00" + }, + { + "name": "symfony/var-exporter", + "version": "v7.0.3", + "source": { + "type": "git", + "url": "https://github.com/symfony/var-exporter.git", + "reference": "1fb79308cb5fc2b44bff6e8af10a5af6812e05b8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/var-exporter/zipball/1fb79308cb5fc2b44bff6e8af10a5af6812e05b8", + "reference": "1fb79308cb5fc2b44bff6e8af10a5af6812e05b8", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "require-dev": { + "symfony/var-dumper": "^6.4|^7.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\VarExporter\\": "" + }, + "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": "Allows exporting any serializable PHP data structure to plain PHP code", + "homepage": "https://symfony.com", + "keywords": [ + "clone", + "construct", + "export", + "hydrate", + "instantiate", + "lazy-loading", + "proxy", + "serialize" + ], + "support": { + "source": "https://github.com/symfony/var-exporter/tree/v7.0.3" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-01-23T15:02:46+00:00" } ], "packages-dev": [ @@ -2476,107 +2805,16 @@ } ], "description": "PHP Doctrine Collections library that adds additional functionality on top of PHP arrays.", - "homepage": "https://www.doctrine-project.org/projects/collections.html", - "keywords": [ - "array", - "collections", - "iterators", - "php" - ], - "support": { - "issues": "https://github.com/doctrine/collections/issues", - "source": "https://github.com/doctrine/collections/tree/2.1.4" - }, - "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%2Fcollections", - "type": "tidelift" - } - ], - "time": "2023-10-03T09:22:33+00:00" - }, - { - "name": "doctrine/event-manager", - "version": "2.0.0", - "source": { - "type": "git", - "url": "https://github.com/doctrine/event-manager.git", - "reference": "750671534e0241a7c50ea5b43f67e23eb5c96f32" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/event-manager/zipball/750671534e0241a7c50ea5b43f67e23eb5c96f32", - "reference": "750671534e0241a7c50ea5b43f67e23eb5c96f32", - "shasum": "" - }, - "require": { - "php": "^8.1" - }, - "conflict": { - "doctrine/common": "<2.9" - }, - "require-dev": { - "doctrine/coding-standard": "^10", - "phpstan/phpstan": "^1.8.8", - "phpunit/phpunit": "^9.5", - "vimeo/psalm": "^4.28" - }, - "type": "library", - "autoload": { - "psr-4": { - "Doctrine\\Common\\": "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" - }, - { - "name": "Marco Pivetta", - "email": "ocramius@gmail.com" - } - ], - "description": "The Doctrine Event Manager is a simple PHP event system that was built to be used with the various Doctrine projects.", - "homepage": "https://www.doctrine-project.org/projects/event-manager.html", + "homepage": "https://www.doctrine-project.org/projects/collections.html", "keywords": [ - "event", - "event dispatcher", - "event manager", - "event system", - "events" + "array", + "collections", + "iterators", + "php" ], "support": { - "issues": "https://github.com/doctrine/event-manager/issues", - "source": "https://github.com/doctrine/event-manager/tree/2.0.0" + "issues": "https://github.com/doctrine/collections/issues", + "source": "https://github.com/doctrine/collections/tree/2.1.4" }, "funding": [ { @@ -2588,24 +2826,24 @@ "type": "patreon" }, { - "url": "https://tidelift.com/funding/github/packagist/doctrine%2Fevent-manager", + "url": "https://tidelift.com/funding/github/packagist/doctrine%2Fcollections", "type": "tidelift" } ], - "time": "2022-10-12T20:59:15+00:00" + "time": "2023-10-03T09:22:33+00:00" }, { "name": "doctrine/inflector", - "version": "2.0.9", + "version": "2.0.10", "source": { "type": "git", "url": "https://github.com/doctrine/inflector.git", - "reference": "2930cd5ef353871c821d5c43ed030d39ac8cfe65" + "reference": "5817d0659c5b50c9b950feb9af7b9668e2c436bc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/inflector/zipball/2930cd5ef353871c821d5c43ed030d39ac8cfe65", - "reference": "2930cd5ef353871c821d5c43ed030d39ac8cfe65", + "url": "https://api.github.com/repos/doctrine/inflector/zipball/5817d0659c5b50c9b950feb9af7b9668e2c436bc", + "reference": "5817d0659c5b50c9b950feb9af7b9668e2c436bc", "shasum": "" }, "require": { @@ -2667,7 +2905,7 @@ ], "support": { "issues": "https://github.com/doctrine/inflector/issues", - "source": "https://github.com/doctrine/inflector/tree/2.0.9" + "source": "https://github.com/doctrine/inflector/tree/2.0.10" }, "funding": [ { @@ -2683,7 +2921,7 @@ "type": "tidelift" } ], - "time": "2024-01-15T18:05:13+00:00" + "time": "2024-02-18T20:23:39+00:00" }, { "name": "doctrine/instantiator", @@ -2832,108 +3070,6 @@ ], "time": "2024-02-05T11:56:58+00:00" }, - { - "name": "doctrine/migrations", - "version": "3.7.2", - "source": { - "type": "git", - "url": "https://github.com/doctrine/migrations.git", - "reference": "47af29eef49f29ebee545947e8b2a4b3be318c8a" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/migrations/zipball/47af29eef49f29ebee545947e8b2a4b3be318c8a", - "reference": "47af29eef49f29ebee545947e8b2a4b3be318c8a", - "shasum": "" - }, - "require": { - "composer-runtime-api": "^2", - "doctrine/dbal": "^3.5.1 || ^4", - "doctrine/deprecations": "^0.5.3 || ^1", - "doctrine/event-manager": "^1.2 || ^2.0", - "php": "^8.1", - "psr/log": "^1.1.3 || ^2 || ^3", - "symfony/console": "^5.4 || ^6.0 || ^7.0", - "symfony/stopwatch": "^5.4 || ^6.0 || ^7.0", - "symfony/var-exporter": "^6.2 || ^7.0" - }, - "conflict": { - "doctrine/orm": "<2.12 || >=4" - }, - "require-dev": { - "doctrine/coding-standard": "^12", - "doctrine/orm": "^2.13 || ^3", - "doctrine/persistence": "^2 || ^3", - "doctrine/sql-formatter": "^1.0", - "ext-pdo_sqlite": "*", - "phpstan/phpstan": "^1.10", - "phpstan/phpstan-deprecation-rules": "^1.1", - "phpstan/phpstan-phpunit": "^1.3", - "phpstan/phpstan-strict-rules": "^1.4", - "phpstan/phpstan-symfony": "^1.3", - "phpunit/phpunit": "^10.3", - "symfony/cache": "^5.4 || ^6.0 || ^7.0", - "symfony/process": "^5.4 || ^6.0 || ^7.0", - "symfony/yaml": "^5.4 || ^6.0 || ^7.0" - }, - "suggest": { - "doctrine/sql-formatter": "Allows to generate formatted SQL with the diff command.", - "symfony/yaml": "Allows the use of yaml for migration configuration files." - }, - "bin": [ - "bin/doctrine-migrations" - ], - "type": "library", - "autoload": { - "psr-4": { - "Doctrine\\Migrations\\": "lib/Doctrine/Migrations" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Benjamin Eberlei", - "email": "kontakt@beberlei.de" - }, - { - "name": "Jonathan Wage", - "email": "jonwage@gmail.com" - }, - { - "name": "Michael Simonson", - "email": "contact@mikesimonson.com" - } - ], - "description": "PHP Doctrine Migrations project offer additional functionality on top of the database abstraction layer (DBAL) for versioning your database schema and easily deploying changes to it. It is a very easy to use and a powerful tool.", - "homepage": "https://www.doctrine-project.org/projects/migrations.html", - "keywords": [ - "database", - "dbal", - "migrations" - ], - "support": { - "issues": "https://github.com/doctrine/migrations/issues", - "source": "https://github.com/doctrine/migrations/tree/3.7.2" - }, - "funding": [ - { - "url": "https://www.doctrine-project.org/sponsorship.html", - "type": "custom" - }, - { - "url": "https://www.patreon.com/phpdoctrine", - "type": "patreon" - }, - { - "url": "https://tidelift.com/funding/github/packagist/doctrine%2Fmigrations", - "type": "tidelift" - } - ], - "time": "2023-12-05T11:35:05+00:00" - }, { "name": "doctrine/orm", "version": "3.0.0", @@ -4439,16 +4575,16 @@ }, { "name": "phpdocumentor/type-resolver", - "version": "1.8.0", + "version": "1.8.1", "source": { "type": "git", "url": "https://github.com/phpDocumentor/TypeResolver.git", - "reference": "fad452781b3d774e3337b0c0b245dd8e5a4455fc" + "reference": "bc3dc91a5e9b14aa06d1d9e90647c5c5a2cc5353" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/fad452781b3d774e3337b0c0b245dd8e5a4455fc", - "reference": "fad452781b3d774e3337b0c0b245dd8e5a4455fc", + "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/bc3dc91a5e9b14aa06d1d9e90647c5c5a2cc5353", + "reference": "bc3dc91a5e9b14aa06d1d9e90647c5c5a2cc5353", "shasum": "" }, "require": { @@ -4491,9 +4627,9 @@ "description": "A PSR-5 based resolver of Class names, Types and Structural Element Names", "support": { "issues": "https://github.com/phpDocumentor/TypeResolver/issues", - "source": "https://github.com/phpDocumentor/TypeResolver/tree/1.8.0" + "source": "https://github.com/phpDocumentor/TypeResolver/tree/1.8.1" }, - "time": "2024-01-11T11:49:22+00:00" + "time": "2024-01-18T19:15:27+00:00" }, { "name": "phpspec/prophecy", @@ -4665,16 +4801,16 @@ }, { "name": "phpstan/phpstan", - "version": "1.10.58", + "version": "1.10.59", "source": { "type": "git", "url": "https://github.com/phpstan/phpstan.git", - "reference": "a23518379ec4defd9e47cbf81019526861623ec2" + "reference": "e607609388d3a6d418a50a49f7940e8086798281" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan/zipball/a23518379ec4defd9e47cbf81019526861623ec2", - "reference": "a23518379ec4defd9e47cbf81019526861623ec2", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/e607609388d3a6d418a50a49f7940e8086798281", + "reference": "e607609388d3a6d418a50a49f7940e8086798281", "shasum": "" }, "require": { @@ -4723,7 +4859,7 @@ "type": "tidelift" } ], - "time": "2024-02-12T20:02:57+00:00" + "time": "2024-02-20T13:59:13+00:00" }, { "name": "phpunit/php-code-coverage", @@ -7149,68 +7285,6 @@ ], "time": "2024-01-23T15:02:46+00:00" }, - { - "name": "symfony/stopwatch", - "version": "v7.0.3", - "source": { - "type": "git", - "url": "https://github.com/symfony/stopwatch.git", - "reference": "983900d6fddf2b0cbaacacbbad07610854bd8112" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/stopwatch/zipball/983900d6fddf2b0cbaacacbbad07610854bd8112", - "reference": "983900d6fddf2b0cbaacacbbad07610854bd8112", - "shasum": "" - }, - "require": { - "php": ">=8.2", - "symfony/service-contracts": "^2.5|^3" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\Stopwatch\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Provides a way to profile code", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/stopwatch/tree/v7.0.3" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2024-01-23T15:02:46+00:00" - }, { "name": "symfony/var-dumper", "version": "v7.0.3", @@ -7294,80 +7368,6 @@ ], "time": "2024-01-23T15:02:46+00:00" }, - { - "name": "symfony/var-exporter", - "version": "v7.0.3", - "source": { - "type": "git", - "url": "https://github.com/symfony/var-exporter.git", - "reference": "1fb79308cb5fc2b44bff6e8af10a5af6812e05b8" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/var-exporter/zipball/1fb79308cb5fc2b44bff6e8af10a5af6812e05b8", - "reference": "1fb79308cb5fc2b44bff6e8af10a5af6812e05b8", - "shasum": "" - }, - "require": { - "php": ">=8.2" - }, - "require-dev": { - "symfony/var-dumper": "^6.4|^7.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\VarExporter\\": "" - }, - "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": "Allows exporting any serializable PHP data structure to plain PHP code", - "homepage": "https://symfony.com", - "keywords": [ - "clone", - "construct", - "export", - "hydrate", - "instantiate", - "lazy-loading", - "proxy", - "serialize" - ], - "support": { - "source": "https://github.com/symfony/var-exporter/tree/v7.0.3" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2024-01-23T15:02:46+00:00" - }, { "name": "thecodingmachine/safe", "version": "v2.5.0", diff --git a/docs/mkdocs.yml b/docs/mkdocs.yml index 0b14915e..2633c76b 100644 --- a/docs/mkdocs.yml +++ b/docs/mkdocs.yml @@ -98,5 +98,4 @@ nav: - Testing: testing.md - Other / Tools: - CLI: cli.md - - Schema Migration: migration.md - Watch Server: watch_server.md diff --git a/docs/pages/cli.md b/docs/pages/cli.md index cdfc36bb..2de5f0d5 100644 --- a/docs/pages/cli.md +++ b/docs/pages/cli.md @@ -1,9 +1,13 @@ # CLI -The library also offers `symfony` cli commands to create or delete `databases`. -It is also possible to manage the `schema` and `projections`. -These commands are `optional` and only wrap existing functionalities -that are also available in this way. +This library provides a `cli` to manage the `event-sourcing` functionalities. + +You can: + +* Create and delete `databases` +* Create, update and delete `schemas` +* Manage `projections` +* Consume `outbox` messages ## Database commands @@ -22,35 +26,23 @@ The database schema can also be created, updated and dropped. !!! note - You can also register doctrine migration commands, - see the [store](./store.md) documentation for this. + You can also register doctrine migration commands. ## Projection commands -The creation, deletion and rebuilding of the projections is also possible via the cli. - -* ProjectionCreateCommand: `event-sourcing:projection:create` -* ProjectionDropCommand: `event-sourcing:projection:drop` -* ProjectionRebuildCommand: `event-sourcing:projection:rebuild` - -!!! note - - The [pipeline](./pipeline.md) will be used to rebuild the projection. - -## Projectionist commands - To manage your projectors there are the following cli commands. -* ProjectionistBootCommand: `event-sourcing:projectionist:boot` -* ProjectionistReactiveCommand: `event-sourcing:projectionist:reactive` -* ProjectionistRemoveCommand: `event-sourcing:projectionist:remove` -* ProjectionistRunCommand: `event-sourcing:projectionist:run` -* ProjectionistStatusCommand: `event-sourcing:projectionist:status` -* ProjectionistTeardownCommand: `event-sourcing:projectionist:teardown` +* ProjectionBootCommand: `event-sourcing:projection:boot` +* ProjectionReactiveCommand: `event-sourcing:projection:reactive` +* ProjectionRebuildCommand: `event-sourcing:projection:rebuild` +* ProjectionRemoveCommand: `event-sourcing:projection:remove` +* ProjectionRunCommand: `event-sourcing:projection:run` +* ProjectionStatusCommand: `event-sourcing:projection:status` +* ProjectionTeardownCommand: `event-sourcing:projection:teardown` !!! note - You can find out more about projectionist [here](projectionist.md). + You can find out more about projections [here](projection.md). ## Outbox commands @@ -74,7 +66,7 @@ use Patchlevel\EventSourcing\Schema\DoctrineSchemaManager; use Symfony\Component\Console\Application; $store = /* define your doctrine store */; -$projectionRepository = /* create a project repository */; +$projectionist = /* create projectionist */; $cli = new Application('Event-Sourcing CLI'); $cli->setCatchExceptions(true); @@ -85,9 +77,13 @@ $schemaManager = new DoctrineSchemaManager(); $cli->addCommands(array( new Command\DatabaseCreateCommand($store, $doctrineHelper), new Command\DatabaseDropCommand($store, $doctrineHelper), - new Command\ProjectionCreateCommand($projectionRepository), - new Command\ProjectionDropCommand($projectionRepository), - new Command\ProjectionRebuildCommand($store, $projectionRepository), + new Command\ProjectionBootCommand($projectionist), + new Command\ProjectionRunCommand($projectionist), + new Command\ProjectionTeardownCommand($projectionist), + new Command\ProjectionRemoveCommand($projectionist), + new Command\ProjectionReactivateCommand($projectionist), + new Command\ProjectionRebuildCommand($projectionist), + new Command\ProjectionStatusCommand($projectionist), new Command\SchemaCreateCommand($store, $schemaManager), new Command\SchemaDropCommand($store, $schemaManager), new Command\SchemaUpdateCommand($store, $schemaManager), @@ -96,7 +92,55 @@ $cli->addCommands(array( $cli->run(); ``` +### Doctrine Migrations + +If you want to use doctrine migrations, you can register the commands like this: + +```php +use Doctrine\DBAL\DriverManager; +use Doctrine\Migrations\DependencyFactory; +use Doctrine\Migrations\Configuration\Migration\PhpFile; +use Doctrine\Migrations\Configuration\Connection\ExistingConnection; +use Doctrine\Migrations\Tools\Console\Command; +use Symfony\Component\Console\Application; +use Patchlevel\EventSourcing\Schema\DoctrineMigrationSchemaProvider; +use Patchlevel\EventSourcing\Schema\DoctrineSchemaDirector; + +$connection = /* create connection */ +$store = /* define your doctrine store */; + +$schemaDirector = new DoctrineSchemaDirector( + $store, + $connection +); + +$migrationConfig = /* define your migration config */; + + +$dependencyFactory = DependencyFactory::fromConnection( + $migrationConfig, + new ExistingConnection($connection) +); + + +$dependencyFactory->setService( + SchemaProvider::class, + new DoctrineMigrationSchemaProvider($schemaDirector) +); + +$cli->addCommands([ + new Command\ExecuteCommand($dependencyFactory, 'event-sourcing:migrations:execute'), + new Command\GenerateCommand($dependencyFactory, 'event-sourcing:migrations:generate'), + new Command\LatestCommand($dependencyFactory, 'event-sourcing:migrations:latest'), + new Command\ListCommand($dependencyFactory, 'event-sourcing:migrations:list'), + new Command\MigrateCommand($dependencyFactory, 'event-sourcing:migrations:migrate'), + new Command\DiffCommand($dependencyFactory, 'event-sourcing:migrations:diff'), + new Command\StatusCommand($dependencyFactory, 'event-sourcing:migrations:status'), + new Command\VersionCommand($dependencyFactory, 'event-sourcing:migrations:version'), +]); +``` + !!! note - You can also register doctrine migration commands, - see the [store](./store.md) documentation for this. + Here you can find more information on how to + [configure doctrine migration](https://www.doctrine-project.org/projects/doctrine-migrations/en/3.3/reference/custom-configuration.html). diff --git a/docs/pages/migration.md b/docs/pages/migration.md deleted file mode 100644 index 8f67e6e7..00000000 --- a/docs/pages/migration.md +++ /dev/null @@ -1,107 +0,0 @@ -# Migration - -You can use doctrine migration, which is known from doctrine orm, to create your schema and keep it in sync. - -!!! warning - - To use the migration CLI commands, you have to configure the [CLI](cli.md) beforehand. - -## Installation - -In order to be able to use `doctrine/migrations`, -you have to install the associated package. - -```bash -composer require doctrine/migrations -``` - -## Configure Migration Schema Provider - -We have added a `schema provider` for doctrine migrations -so that you just have to plug the whole thing together. - -```php -use Patchlevel\EventSourcing\Schema\DoctrineMigrationSchemaProvider; -use Patchlevel\EventSourcing\Schema\DoctrineSchemaDirector; - -$schemaDirector = new DoctrineSchemaDirector( - $store, - $connection -); - -$schemaProvider = new DoctrineMigrationSchemaProvider($schemaDirector); -``` - -## CLI example - -You can plug this together, for example, as follows to create CLI applications like `cli.php`: - -```php -use Doctrine\DBAL\DriverManager; -use Doctrine\Migrations\DependencyFactory; -use Doctrine\Migrations\Configuration\Migration\PhpFile; -use Doctrine\Migrations\Configuration\Connection\ExistingConnection; -use Doctrine\Migrations\Tools\Console\Command; -use Symfony\Component\Console\Application; -use Patchlevel\EventSourcing\Schema\DoctrineMigrationSchemaProvider; -use Patchlevel\EventSourcing\Schema\DoctrineSchemaDirector; - -$connection = DriverManager::getConnection([ - 'url' => 'mysql://user:secret@localhost/app' -]); - -$config = new PhpFile('migrations.php'); - -$dependencyFactory = DependencyFactory::fromConnection( - $config, - new ExistingConnection($connection) -); - -$schemaDirector = new DoctrineSchemaDirector( - $store, - $connection -); - -$dependencyFactory->setService( - SchemaProvider::class, - new DoctrineMigrationSchemaProvider($schemaDirector) -); - -$cli = new Application('Event-Sourcing CLI'); -$cli->setCatchExceptions(true); - -$cli->addCommands([ - - // other cli commands - - new Command\ExecuteCommand($dependencyFactory, 'event-sourcing:migrations:execute'), - new Command\GenerateCommand($dependencyFactory, 'event-sourcing:migrations:generate'), - new Command\LatestCommand($dependencyFactory, 'event-sourcing:migrations:latest'), - new Command\ListCommand($dependencyFactory, 'event-sourcing:migrations:list'), - new Command\MigrateCommand($dependencyFactory, 'event-sourcing:migrations:migrate'), - new Command\DiffCommand($dependencyFactory, 'event-sourcing:migrations:diff'), - new Command\StatusCommand($dependencyFactory, 'event-sourcing:migrations:status'), - new Command\VersionCommand($dependencyFactory, 'event-sourcing:migrations:version'), -]); - -$cli->run(); -``` - -!!! note - - Here you can find more information on how to - [configure doctrine migration](https://www.doctrine-project.org/projects/doctrine-migrations/en/3.3/reference/custom-configuration.html). - - -## Migration commands - -There are some commands to use the migration feature. - -* ExecuteCommand: `event-sourcing:migrations:execute` -* GenerateCommand: `event-sourcing:migrations:generate` -* LatestCommand: `event-sourcing:migrations:latest` -* ListCommand: `event-sourcing:migrations:list` -* MigrateCommand: `event-sourcing:migrations:migrate` -* DiffCommand: `event-sourcing:migrations:diff` -* StatusCommand: `event-sourcing:migrations:status` -* VersionCommand: `event-sourcing:migrations:version` diff --git a/docs/pages/store.md b/docs/pages/store.md index 995fc485..10a7b354 100644 --- a/docs/pages/store.md +++ b/docs/pages/store.md @@ -1,7 +1,14 @@ # Store -In the end, the events/messages have to be saved somewhere. -The library is based on [doctrine dbal](https://www.doctrine-project.org/projects/dbal.html). +In the end, the messages have to be saved somewhere. +Each message contains an event and the associated headers. + +!!! note + + More information about the message can be found [here](event_bus.md). + +The store is optimized to efficiently store and load events for aggregates. +We currently only offer one [doctrine dbal](https://www.doctrine-project.org/projects/dbal.html) store. ## Create DBAL connection @@ -20,15 +27,10 @@ $connection = DriverManager::getConnection([ You can find out more about how to create a connection [here](https://www.doctrine-project.org/projects/doctrine-dbal/en/latest/reference/configuration.html) -## Store types - -We only offer one Doctrine Dbal Store by default. But you can implement your own store if you want to. +## Configure Store -### Doctrine DBAL Store - -With the `DoctrineDbalStore` everything is saved in one table. -The dbal connection is needed, a mapping of the aggregate class and aggregate name -and the table name. +You can create a store with the `DoctrineDbalStore` class. +The store needs a dbal connection, an event serializer, an aggregate registry and a table name. ```php use Patchlevel\EventSourcing\Metadata\AggregateRoot\AggregateRootRegistry; @@ -45,31 +47,22 @@ $store = new DoctrineDbalStore( ); ``` -## Transaction - -There is also the possibility of executing a function in a transaction. -Then dbal takes care of starting a transaction, committing it and then possibly rollback it again. - -```php -$store->transactional(function () use ($command, $bankAccountRepository) { - $accountFrom = $bankAccountRepository->get($command->from()); - $accountTo = $bankAccountRepository->get($command->to()); - - $accountFrom->transferMoney($command->to(), $command->amount()); - $accountTo->receiveMoney($command->from(), $command->amount()); - - $bankAccountRepository->save($accountFrom); - $bankAccountRepository->save($accountTo); -}); -``` - -!!! tip +## Schema - To ensure that all listeners are executed for the released events - or that the listeners are not executed if the transaction fails, - you can use the [outbox](outbox.md) pattern for it. +The table structure of the `DoctrineDbalStore` looks like this: -## Schema +| Column | Type | Description | +|------------------|----------|--------------------------------------------------| +| id | bigint | The index of the whole stream (autoincrement) | +| aggregate | string | The name of the aggregate | +| aggregate_id | string | The id of the aggregate | +| playhead | int | The current playhead of the aggregate | +| event | string | The name of the event | +| payload | json | The payload of the event | +| recorded_on | datetime | The date when the event was recorded | +| new_stream_start | bool | If the event is the first event of the aggregate | +| archived | bool | If the event is archived | +| custom_headers | json | Custom headers for the event | With the help of the `SchemaDirector`, the database structure can be created, updated and deleted. @@ -77,7 +70,11 @@ With the help of the `SchemaDirector`, the database structure can be created, up You can also use doctrine [migration](migration.md) to create and keep your schema in sync. -### Create SchemaDirector +### Schema Director + +The `SchemaDirector` is responsible for creating, updating and deleting the database schema. +The `DoctrineSchemaDirector` is a concrete implementation of the `SchemaDirector` for doctrine dbal. +Additionally, it implements the `DryRunSchemaDirector` interface, to show the sql statements that would be executed. ```php use Patchlevel\EventSourcing\Schema\DoctrineSchemaDirector; @@ -88,20 +85,224 @@ $schemaDirector = new DoctrineSchemaDirector( ); ``` -### Create schema +!!! note + + How to setup cli commands for schema director can be found [here](cli.md). + +#### Create schema + +You can create the table from scratch using the `create` method. ```php $schemaDirector->create(); ``` -### Update schema +Or can give you back which SQL statements would be necessary for this. +Either for a dry run, or to define your own migrations. + +```php +$sql = $schemaDirector->dryRunCreate(); +``` + +#### Update schema + +The update method compares the current state in the database and how the table should be structured. +As a result, the diff is executed to bring the table to the desired state. ```php $schemaDirector->update(); ``` -### Drop schema +Or can give you back which SQL statements would be necessary for this. + +```php +$sql = $schemaDirector->dryRunUpdate(); +``` + +#### Drop schema + +You can also delete the table with the `drop` method. ```php $schemaDirector->drop(); ``` + +Or can give you back which SQL statements would be necessary for this. + +```php +$sql = $schemaDirector->dryRunDrop(); +``` + +### Doctrine Migrations + +You can use [doctrine migration](https://www.doctrine-project.org/projects/migrations.html), +which is known from [doctrine orm](https://www.doctrine-project.org/projects/orm.html), +to create your schema and keep it in sync. +We have added a `DoctrineMigrationSchemaProvider` for doctrine migrations so that you just have to plug the whole thing +together. + +```php +use Patchlevel\EventSourcing\Schema\DoctrineMigrationSchemaProvider; +use Patchlevel\EventSourcing\Schema\DoctrineSchemaDirector; + +// event sourcing schema director configuration + +$schemaDirector = new DoctrineSchemaDirector( + $store, + $connection +); + +$schemaProvider = new DoctrineMigrationSchemaProvider($schemaDirector); + +// doctrine migration configuration + +$dependencyFactory = DependencyFactory::fromConnection( + $config, + new ExistingConnection($connection) +); + +$dependencyFactory->setService( + SchemaProvider::class, + $schemaProvider +); +``` + +!!! note + + Here you can find more information on how to + [configure doctrine migration](https://www.doctrine-project.org/projects/doctrine-migrations/en/3.3/reference/custom-configuration.html). + +!!! note + + How to setup cli commands for doctrine migration can be found [here](cli.md). + +## Usage + +The store has a few methods to interact with the database. + +### Load + +You can load all events from an aggregate with the `load` method. +This method returns a `Stream` object, which is a collection of events. + +```php +$stream = $store->load(); +``` + +The load method also has a few parameters to filter, limit and sort the events. + +```php +use Patchlevel\EventSourcing\Store\Criteria; + +$stream = $store->load( + new Criteria() // filter criteria + 100 // limit + 50, // offset + true, // latest first +); +``` + +#### Criteria + +The `Criteria` object is used to filter the events. + +```php +use Patchlevel\EventSourcing\Store\Criteria; + +$criteria = new Criteria( + aggregateName: 'profile', + aggregateId: 'e3e3e3e3-3e3e-3e3e-3e3e-3e3e3e3e3e3e', + fromIndex: 100, + fromPlayhead: 2, + archived: true, +); +``` + +!!! note + + The individual criteria must all apply, but not all of them have to be set. + +#### Stream + +The load method returns a `Stream` object and is a generator. +This means that the messages are only loaded when they are needed. + +```php +use Patchlevel\EventSourcing\Store\Stream; + +/** @var Stream $stream */ +$stream->index(); // get the index of the stream +$stream->position(); // get the current position of the stream +$stream->current(); // get the current event +$stream->next(); // move to the next event +$stream->end(); // check if the stream is at the end + +foreach ($stream as $message) { + $message->event(); // get the event +} +``` + +!!! note + + You can find more information about the `Message` object [here](event_bus.md). + +!!! warning + + The stream cannot rewind, so you can only iterate over it once. + If you want to iterate over it again, you have to call the `load` method again. + +### Count + +You can count the number of events in the store with the `count` method. + +```php +$count = $store->count(); +``` + +The count method also has the possibility to filter the events. + +```php +use Patchlevel\EventSourcing\Store\Criteria; + +$count = $store->count( + new Criteria() // filter criteria +); +``` + +### Save + +You can save a message with the `save` method. + +```php +$store->save($message); +$store->save($message1, $message2, $message3); +$store->save(...$messages); +``` + +!!! note + + The saving happens in a transaction, so all messages are saved or none. + +### Delete & Update + +It is not possible to delete or update events. +In event sourcing, the events are immutable. + +### Transaction + +There is also the possibility of executing a function in a transaction. +Then dbal takes care of starting a transaction, committing it and then possibly rollback it again. + +```php +$store->transactional(function () use ($command, $bankAccountRepository) { + $accountFrom = $bankAccountRepository->get($command->from()); + $accountTo = $bankAccountRepository->get($command->to()); + + $accountFrom->transferMoney($command->to(), $command->amount()); + $accountTo->receiveMoney($command->from(), $command->amount()); + + $bankAccountRepository->save($accountFrom); + $bankAccountRepository->save($accountTo); +}); +``` + diff --git a/src/Store/DoctrineDbalStore.php b/src/Store/DoctrineDbalStore.php index f68f9c66..c81bb3f9 100644 --- a/src/Store/DoctrineDbalStore.php +++ b/src/Store/DoctrineDbalStore.php @@ -256,7 +256,7 @@ public function configureSchema(Schema $schema, Connection $connection): void $table->addColumn('payload', Types::JSON) ->setNotnull(true); $table->addColumn('recorded_on', Types::DATETIMETZ_IMMUTABLE) - ->setNotnull(false); + ->setNotnull(true); $table->addColumn('new_stream_start', Types::BOOLEAN) ->setNotnull(true) ->setDefault(false);