componenta/cqrs-app

Componenta application integration for CQRS discovery compilation

Maintainers

Package info

github.com/componenta/cqrs-app

pkg:composer/componenta/cqrs-app

Transparency log

Statistics

Installs: 22

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

v3.0.3 2026-08-16 17:47 UTC

This package is auto-updated.

Last update: 2026-08-17 09:39:21 UTC


README

componenta/cqrs-app adds application-level discovery and build-time map compilation for componenta/cqrs.

It does not contain runtime middleware, transports, or console workers. Install the relevant optional CQRS packages for those concerns.

Installation

composer require componenta/cqrs-app

Dependencies

Dependency Purpose
PHP ^8.4 Modern language features and strict types.
componenta/app Application discovery and production build integration.
componenta/class-finder Class discovery and listener compiler contracts.
componenta/config Configuration and factory integration.
componenta/cqrs Core CQRS runtime, map contracts, and config keys.
componenta/tokenizer Supplies ClassInfo and its existing reflector to discovery.
psr/container Service lookup.

What It Registers

Config section Entries
factories CqrsDiscoveryIndex, CqrsMapCompiler, and the application implementation of CqrsMapProviderInterface.
ClassFinderConfigKey::LISTENERS The single CqrsDiscoveryIndex listener.
CompileConfigKey::LISTENER_COMPILERS The compiler that emits ConfigKey::CQRS_MAP.
AppConfigKey::AUTOWIRE_ENTRY_CONTRIBUTORS The discovery index that contributes discovered handlers and listeners to DI compilation.

Usage

Register the core provider first and the application provider second:

return [
    new Componenta\CQRS\ConfigProvider(),
    new Componenta\CQRS\App\ConfigProvider(),
];

componenta/cqrs provides the standalone CqrsMapProviderInterface binding backed by configured data. componenta/cqrs-app replaces that one binding with an application factory. In development the factory returns a composite of the configured and discovered maps; outside development it returns the configured provider reading the compiled map.

All core runtime consumers continue to depend on the same CqrsMapProviderInterface: command, query and listener locators, command metadata, and the compiler therefore observe one effective map.

Use discovery attributes in application code:

use Componenta\CQRS\Command\Attribute\AsCommandHandler;

#[AsCommandHandler]
final readonly class PublishPostHandler
{
    public function __invoke(PublishPostCommand $command): void
    {
        // Handle command.
    }
}

Discovery And Metadata

CqrsDiscoveryIndex reads ClassInfo::$reflector once per class and collects command handlers, query handlers, listeners, known command names, and configured command metadata attributes. It validates public non-static handler methods, rejects conflicting handlers, deduplicates identical listeners, and performs deterministic sorting in finalize().

Optional packages add metadata without changing the compiler by appending an attribute class to ConfigKey::COMMAND_METADATA_ATTRIBUTES. The factory validates that every entry exists and is declared with #[Attribute].

ConfigKey::DISCOVERY_ENABLED may explicitly enable or disable the live overlay. When omitted, live discovery is enabled only for exact APP_ENV=development. Every other environment requires a compiled CQRS map and rejects an attempt to enable runtime discovery.

Production Build

With componenta/app-console, build the artifact before starting production:

APP_ENV=development php bin/console.php app:build

The application provider first produces the same effective map used by development dispatch: configured map plus discovery map, merged through CqrsMap::merge(). CqrsMapCompiler serializes that effective map as one deterministic versioned artifact. The build merge replaces numeric descriptor positions instead of appending the configured portion a second time.

Production reads the resulting complete artifact through the same CqrsMapProviderInterface, without scanning application classes. Metadata for a known compiled command never falls back to reflection; an unknown command may still use the reflection provider.

An old CQRS key, unsupported map version, or missing non-development map fails with an instruction to clear caches and rebuild. After upgrading from v1, remove the config, discovery, old CQRS, and legacy container caches before running app:build.

Optional Runtime Packages

Install separate packages for runtime concerns:

Package Adds
componenta/cqrs-policy Command/query policy middleware.
componenta/cqrs-retry Retry middleware.
componenta/cqrs-lock Resource lock middleware.
componenta/cqrs-transaction-cycle Cycle Database transaction middleware.
componenta/cqrs-transport Async transport middleware, contracts, serializer, and worker.
componenta/cqrs-transport-cycle Cycle Database transport implementation.
componenta/cqrs-transport-console cqrs:worker Symfony Console command.