--- name: add-command description: Scaffold a new CQRS command with handler, validator, and DI registration. Use when the user wants to add a new command to a project. argument-hint: --- # Add Command Scaffold a new command based on: $ARGUMENTS ## Instructions ### 1. Determine the command name The name must express **domain intent**, not CRUD. If the user's description sounds like CRUD, translate it: - "create a user" → `RegisterUserCommand` - "update the order status" → contextual: `ShipOrderCommand`, `CancelOrderCommand`, `ApproveOrderCommand` - "delete an account" → `DeactivateAccountCommand` or `CloseAccountCommand` Ask the user to clarify if the intent is ambiguous (e.g., "update order" could mean many things). ### 2. Determine the feature folder Place the file in the appropriate feature folder: `Features/{DomainArea}/` If the folder doesn't exist, create it. If the project doesn't use `Features/` yet, check the existing structure and follow the same pattern. ### 3. Create the file Create a single file `Features/{DomainArea}/{CommandName}Command.cs` containing all three classes: ```csharp using FluentValidation; using Svrnty.CQRS.Abstractions; namespace {ProjectNamespace}.Features.{DomainArea}; // 1. Command POCO — record type, properties with defaults public record {CommandName}Command { // Properties based on user description // Strings default to string.Empty, collections to [] } // 2. Validator — rules in constructor, always include .WithMessage() public class {CommandName}CommandValidator : AbstractValidator<{CommandName}Command> { public {CommandName}CommandValidator() { // Validation rules based on command properties } } // 3. Handler — always async with CancellationToken public class {CommandName}CommandHandler : ICommandHandler<{CommandName}Command, {ResultType}> { public Task<{ResultType}> HandleAsync({CommandName}Command command, CancellationToken cancellationToken = default) { throw new NotImplementedException(); } } ``` If the command has **no return value**, use `ICommandHandler<{CommandName}Command>` (single generic param) with `Task HandleAsync(...)`. ### 4. Register in DI Find the project's service registration (typically `Program.cs` or a dedicated registration method) and add: ```csharp // With validator (preferred) builder.Services.AddCommand<{CommandName}Command, {ResultType}, {CommandName}CommandHandler, {CommandName}CommandValidator>(); // Without validator builder.Services.AddCommand<{CommandName}Command, {ResultType}, {CommandName}CommandHandler>(); // No return value + validator builder.Services.AddCommand<{CommandName}Command, {CommandName}CommandHandler, {CommandName}CommandValidator>(); ``` Ensure the `using Svrnty.CQRS.FluentValidation;` namespace is imported if using the validator overload. ### 5. Proto message (if project uses gRPC) If the project has a `Protos/` directory, add the corresponding proto message: ```protobuf // In the CommandService definition rpc {CommandName} ({CommandName}CommandRequest) returns ({CommandName}CommandResponse); // Request message message {CommandName}CommandRequest { // fields matching command properties, snake_case, numbered sequentially } // Response message message {CommandName}CommandResponse { {result_type} result = 1; // omit if command has no return value } ``` ### 6. Summary After creating everything, list what was created and where.