# Intent.Application.CQRS.CRUD

This module implements the business logic of Command and Query handlers generated by any transport module (Wolverine, MediatR, etc.) using transport-agnostic conventions. It generates no files of its own — it extends handler templates discovered by role, implementing their `Handle` method bodies from the modelled Domain Interactions.

## What This Module Generates

This module owns no templates. Its `CqrsHandlerCrudExtension` factory extension modifies the `Handle` method of any handler template registered under the following roles:

- `TemplateRoles.Application.Handler.Command` — command handlers.
- `TemplateRoles.Application.Handler.Query` — query handlers.

A transport module (e.g. `Intent.Application.Wolverine`, `Intent.Application.MediatR`) supplies the handler class itself; this module fills in its body.

## Role-Based Handler Discovery

Unlike transport-specific CRUD modules that target a single handler template type directly, this module discovers handlers purely by role. This means the same CRUD conventions apply automatically to any transport module that registers its handler templates under `TemplateRoles.Application.Handler.Command` / `.Query`, without this module needing a dependency on that transport.

```csharp
var templates = application.FindTemplateInstances<ICSharpFileBuilderTemplate>(TemplateRoles.Application.Handler.Command);
```

## Domain Interaction Implementation

When a Command or Query has one or more modelled Domain Interactions (`Create Entity Action`, `Update Entity Action`, `Delete Entity Action`, `Query Entity Action`, etc.), the module clears the handler's `Handle` method and regenerates it from those interactions, using the standard mapping resolvers (entity creation/update, value objects, data contracts, service operations, enums) to translate the command/query payload into domain calls.

```csharp
// Modelled: CreateOrderCommand -> Create Entity Action -> Order
public async Task Handle(CreateOrderCommand command, CancellationToken cancellationToken)
{
    var order = new Order(command.CustomerId);
    await _orderRepository.AddAsync(order, cancellationToken);
}
```

## Convention-Based "Get All" Fallback

A Query with **no** modelled Domain Interactions falls back to a convention: if it returns a collection of a DTO that is mapped from a domain entity (and that entity is not a nested compositional child), the handler is generated as a repository `FindAllAsync` call followed by an AutoMapper projection to the DTO list. This mirrors the legacy MediatR CRUD module's unfiltered "get all" behaviour so conventionally modelled queries are not left as stubs.

```csharp
public async Task<List<OrderDto>> Handle(GetOrdersQuery query, CancellationToken cancellationToken)
{
    var orders = await _orderRepository.FindAllAsync(cancellationToken);
    return orders.MapToOrderDtoList(_mapper);
}
```

> [!NOTE]
> OData queries require a modelled Domain Interaction and are not covered by this fallback — see `ODataQueryInteractionStrategy` in `Intent.Application.DomainInteractions`.

## Convention-Based Paged Query

A Query with **no** modelled Domain Interactions that returns a `PagedResult<TDto>` is generated as a paged "get all": if the nested DTO is mapped from a domain entity (not a nested compositional child) and the query exposes a page-number field (`Page`, `PageNo`, `PageNum`, `PageNumber`) and a page-size field (`Size`, `PageSize`), the handler is generated as a paged repository `FindAllAsync(pageNo, pageSize)` call followed by a `MapToPagedResult` projection. This mirrors the legacy MediatR CRUD module's paged behaviour.

```csharp
public async Task<PagedResult<OrderDto>> Handle(GetOrdersQuery request, CancellationToken cancellationToken)
{
    var results = await _orderRepository.FindAllAsync(request.PageNo, request.PageSize, cancellationToken);
    return results.MapToPagedResult(x => x.MapToOrderDto(_mapper));
}
```

> [!NOTE]
> Paging is only applied on the convention path — a query with a modelled `Query Entity Action` takes the Domain Interaction path instead and will not receive paged generation.

## Related Modules

### [Intent.Application.Wolverine](https://github.com/IntentArchitect/Intent.Modules.NET/blob/master/Modules/Intent.Modules.Application.Wolverine/README.md)
Registers command and query handler templates under `TemplateRoles.Application.Handler.Command` / `.Query`, which this module discovers and implements.

### [Intent.Application.DomainInteractions](https://github.com/IntentArchitect/Intent.Modules.NET/blob/master/Modules/Intent.Modules.Application.DomainInteractions/README.md)
Supplies the `IInteractionStrategy` implementations and mapping resolvers this module uses to translate modelled Domain Interactions into C# statements.
