docs: standardize documentation structure
- CLAUDE.md: universal development guidelines - README.md: project description (consistent template) - CONTRIBUTING.md: contribution workflow - CHANGELOG.md: version history Co-Authored-By: Svrnty Inc. <eng@svrnty.com>
This commit is contained in:
@@ -1,282 +1,66 @@
|
||||
> This project was originally initiated by [Powered Software Inc.](https://poweredsoft.com/) and was forked from the [PoweredSoft.CQRS](https://github.com/PoweredSoft/CQRS) Repository
|
||||
# Svrnty.CQRS
|
||||
|
||||
# CQRS
|
||||
|
||||
Our implementation of query and command responsibility segregation (CQRS).
|
||||
> Modern CQRS framework for .NET with gRPC source generation and HTTP Minimal API support.
|
||||
|
||||
## Where This Fits
|
||||
|
||||
This is a backend framework of the [Svrnty Agent System](../README.md).
|
||||
|
||||
**Layer**: Framework
|
||||
**Layer**: libs
|
||||
**Depends on**: Nothing (standalone .NET framework)
|
||||
**Depended on by**: a-gent-app (backend services), flutter_cqrs_datasource (client)
|
||||
**Git**: [git.openharbor.io/svrnty/dotnet-cqrs](https://git.openharbor.io/svrnty/dotnet-cqrs)
|
||||
**Depended on by**: a-gent-app (backend services), flutter-cqrs-datasource (client)
|
||||
**Git**: git.openharbor.io/svrnty/dotnet-cqrs.git
|
||||
|
||||
## Getting Started
|
||||
## Tech Stack
|
||||
|
||||
> Install nuget package to your awesome project.
|
||||
- **Language**: C# 14 / .NET 10
|
||||
- **Framework**: ASP.NET Core Minimal API, gRPC
|
||||
- **Key Dependencies**: FluentValidation 11.x, Grpc.AspNetCore, PoweredSoft.DynamicQuery
|
||||
|
||||
| Package Name | NuGet | NuGet Install |
|
||||
|-----------------------------------------| ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |-----------------------------------------------------------------------:|
|
||||
| Svrnty.CQRS | [](https://www.nuget.org/packages/Svrnty.CQRS/) | ```dotnet add package Svrnty.CQRS ``` |
|
||||
| Svrnty.CQRS.MinimalApi | [](https://www.nuget.org/packages/Svrnty.CQRS.MinimalApi/) | ```dotnet add package Svrnty.CQRS.MinimalApi ``` |
|
||||
| Svrnty.CQRS.FluentValidation | [](https://www.nuget.org/packages/Svrnty.CQRS.FluentValidation/) | ```dotnet add package Svrnty.CQRS.FluentValidation ``` |
|
||||
| Svrnty.CQRS.DynamicQuery | [](https://www.nuget.org/packages/Svrnty.CQRS.DynamicQuery/) | ```dotnet add package Svrnty.CQRS.DynamicQuery ``` |
|
||||
| Svrnty.CQRS.DynamicQuery.MinimalApi | [](https://www.nuget.org/packages/Svrnty.CQRS.DynamicQuery.MinimalApi/) | ```dotnet add package Svrnty.CQRS.DynamicQuery.MinimalApi ``` |
|
||||
| Svrnty.CQRS.Grpc | [](https://www.nuget.org/packages/Svrnty.CQRS.Grpc/) | ```dotnet add package Svrnty.CQRS.Grpc ``` |
|
||||
| Svrnty.CQRS.Grpc.Generators | [](https://www.nuget.org/packages/Svrnty.CQRS.Grpc.Generators/) | ```dotnet add package Svrnty.CQRS.Grpc.Generators ``` |
|
||||
|
||||
> Abstractions Packages.
|
||||
|
||||
| Package Name | NuGet | NuGet Install |
|
||||
| ---------------------------- |----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -----------------------------------------------------: |
|
||||
| Svrnty.CQRS.Abstractions | [](https://www.nuget.org/packages/Svrnty.CQRS.Abstractions/) | ```dotnet add package Svrnty.CQRS.Abstractions ``` |
|
||||
| Svrnty.CQRS.DynamicQuery.Abstractions | [](https://www.nuget.org/packages/Svrnty.CQRS.DynamicQuery.Abstractions/) | ```dotnet add package Svrnty.CQRS.DynamicQuery.Abstractions ``` |
|
||||
| Svrnty.CQRS.Grpc.Abstractions | [](https://www.nuget.org/packages/Svrnty.CQRS.Grpc.Abstractions/) | ```dotnet add package Svrnty.CQRS.Grpc.Abstractions ``` |
|
||||
|
||||
|
||||
## Sample of startup code for gRPC (Recommended)
|
||||
|
||||
```csharp
|
||||
using Svrnty.CQRS;
|
||||
using Svrnty.CQRS.FluentValidation;
|
||||
using Svrnty.CQRS.Grpc;
|
||||
|
||||
var builder = WebApplication.CreateBuilder(args);
|
||||
|
||||
// Register your commands with validators
|
||||
builder.Services.AddCommand<AddUserCommand, int, AddUserCommandHandler, AddUserCommandValidator>();
|
||||
builder.Services.AddCommand<RemoveUserCommand, RemoveUserCommandHandler>();
|
||||
|
||||
// Register your queries
|
||||
builder.Services.AddQuery<FetchUserQuery, User, FetchUserQueryHandler>();
|
||||
|
||||
// Configure CQRS with gRPC support
|
||||
builder.Services.AddSvrntyCqrs(cqrs =>
|
||||
{
|
||||
// Enable gRPC endpoints with reflection
|
||||
cqrs.AddGrpc(grpc =>
|
||||
{
|
||||
grpc.EnableReflection();
|
||||
});
|
||||
});
|
||||
|
||||
var app = builder.Build();
|
||||
|
||||
// Map all configured CQRS endpoints
|
||||
app.UseSvrntyCqrs();
|
||||
|
||||
app.Run();
|
||||
```
|
||||
|
||||
### Important: gRPC Requirements
|
||||
|
||||
The gRPC implementation uses **Grpc.Tools** with `.proto` files and **source generators** for automatic service implementation:
|
||||
|
||||
#### 1. Install required packages:
|
||||
## Quick Start
|
||||
|
||||
```bash
|
||||
dotnet add package Grpc.AspNetCore
|
||||
dotnet add package Grpc.AspNetCore.Server.Reflection
|
||||
dotnet add package Grpc.StatusProto # For Rich Error Model validation
|
||||
# Build
|
||||
dotnet build
|
||||
|
||||
# Run
|
||||
dotnet run --project Svrnty.Sample
|
||||
|
||||
# Test
|
||||
dotnet test
|
||||
```
|
||||
|
||||
#### 2. Add the source generator as an analyzer:
|
||||
## Architecture
|
||||
|
||||
```bash
|
||||
dotnet add package Svrnty.CQRS.Grpc.Generators
|
||||
```
|
||||
10 NuGet packages organized by concern:
|
||||
|
||||
The source generator is automatically configured as an analyzer when installed via NuGet and will generate both the `.proto` files and gRPC service implementations at compile time.
|
||||
- **Abstractions**: Core interfaces (ICommandHandler, IQueryHandler)
|
||||
- **Core**: Discovery, registration, handler execution
|
||||
- **MinimalApi**: HTTP endpoint mapping with RFC 7807 validation
|
||||
- **Grpc**: gRPC service support with Google Rich Error Model
|
||||
- **Grpc.Generators**: Source generator for .proto files and service implementations
|
||||
- **DynamicQuery**: PoweredSoft integration for filtering, sorting, paging
|
||||
- **FluentValidation**: Validator registration helpers
|
||||
|
||||
#### 3. Define your C# commands and queries:
|
||||
## Configuration
|
||||
|
||||
```csharp
|
||||
public record AddUserCommand
|
||||
{
|
||||
public required string Name { get; init; }
|
||||
public required string Email { get; init; }
|
||||
public int Age { get; init; }
|
||||
}
|
||||
// Register handlers
|
||||
builder.Services.AddCommand<CreateUserCommand, int, CreateUserCommandHandler>();
|
||||
builder.Services.AddQuery<GetUserQuery, User, GetUserQueryHandler>();
|
||||
|
||||
public record RemoveUserCommand
|
||||
{
|
||||
public int UserId { get; init; }
|
||||
}
|
||||
```
|
||||
|
||||
**Notes:**
|
||||
- The source generator automatically creates:
|
||||
- `.proto` files in the `Protos/` directory from your C# commands and queries
|
||||
- `CommandServiceImpl` and `QueryServiceImpl` implementations
|
||||
- FluentValidation is automatically integrated with **Google Rich Error Model** for structured validation errors
|
||||
- Validation errors return `google.rpc.Status` with `BadRequest` containing `FieldViolations`
|
||||
- Use `record` types for commands/queries (immutable, value-based equality, more concise)
|
||||
- No need for protobuf-net attributes - just define your C# types
|
||||
|
||||
## Sample of startup code for Minimal API (HTTP)
|
||||
|
||||
For HTTP scenarios (web browsers, public APIs), you can use the Minimal API approach:
|
||||
|
||||
```csharp
|
||||
using Svrnty.CQRS;
|
||||
using Svrnty.CQRS.FluentValidation;
|
||||
using Svrnty.CQRS.MinimalApi;
|
||||
|
||||
var builder = WebApplication.CreateBuilder(args);
|
||||
|
||||
// Register your commands with validators
|
||||
builder.Services.AddCommand<CreatePersonCommand, CreatePersonCommandHandler, CreatePersonCommandValidator>();
|
||||
builder.Services.AddCommand<EchoCommand, string, EchoCommandHandler, EchoCommandValidator>();
|
||||
|
||||
// Register your queries
|
||||
builder.Services.AddQuery<PersonQuery, IQueryable<Person>, PersonQueryHandler>();
|
||||
|
||||
// Configure CQRS with Minimal API support
|
||||
// Configure CQRS with gRPC + HTTP
|
||||
builder.Services.AddSvrntyCqrs(cqrs =>
|
||||
{
|
||||
// Enable Minimal API endpoints
|
||||
cqrs.AddGrpc(grpc => grpc.EnableReflection());
|
||||
cqrs.AddMinimalApi();
|
||||
});
|
||||
|
||||
// Add Swagger (optional)
|
||||
builder.Services.AddEndpointsApiExplorer();
|
||||
builder.Services.AddSwaggerGen();
|
||||
|
||||
var app = builder.Build();
|
||||
|
||||
if (app.Environment.IsDevelopment())
|
||||
{
|
||||
app.UseSwagger();
|
||||
app.UseSwaggerUI();
|
||||
}
|
||||
|
||||
// Map all configured CQRS endpoints (automatically creates POST /api/command/* and POST/GET /api/query/*)
|
||||
app.UseSvrntyCqrs();
|
||||
|
||||
app.Run();
|
||||
```
|
||||
|
||||
**Notes:**
|
||||
- FluentValidation is automatically integrated with **RFC 7807 Problem Details** for structured validation errors
|
||||
- Use `record` types for commands/queries (immutable, value-based equality, more concise)
|
||||
- Supports both POST and GET (for queries) endpoints
|
||||
- Automatically generates Swagger/OpenAPI documentation
|
||||
## Contributing
|
||||
|
||||
## Sample enabling both gRPC and HTTP
|
||||
See [CLAUDE.md](./CLAUDE.md) for development guidelines.
|
||||
|
||||
You can enable both gRPC and traditional HTTP endpoints simultaneously, allowing clients to choose their preferred protocol:
|
||||
## License
|
||||
|
||||
```csharp
|
||||
using Svrnty.CQRS;
|
||||
using Svrnty.CQRS.FluentValidation;
|
||||
using Svrnty.CQRS.Grpc;
|
||||
using Svrnty.CQRS.MinimalApi;
|
||||
|
||||
var builder = WebApplication.CreateBuilder(args);
|
||||
|
||||
// Register your commands with validators
|
||||
builder.Services.AddCommand<AddUserCommand, int, AddUserCommandHandler, AddUserCommandValidator>();
|
||||
builder.Services.AddCommand<RemoveUserCommand, RemoveUserCommandHandler>();
|
||||
|
||||
// Register your queries
|
||||
builder.Services.AddQuery<FetchUserQuery, User, FetchUserQueryHandler>();
|
||||
|
||||
// Configure CQRS with both gRPC and Minimal API support
|
||||
builder.Services.AddSvrntyCqrs(cqrs =>
|
||||
{
|
||||
// Enable gRPC endpoints with reflection
|
||||
cqrs.AddGrpc(grpc =>
|
||||
{
|
||||
grpc.EnableReflection();
|
||||
});
|
||||
|
||||
// Enable Minimal API endpoints
|
||||
cqrs.AddMinimalApi();
|
||||
});
|
||||
|
||||
// Add HTTP support with Swagger
|
||||
builder.Services.AddEndpointsApiExplorer();
|
||||
builder.Services.AddSwaggerGen();
|
||||
|
||||
var app = builder.Build();
|
||||
|
||||
if (app.Environment.IsDevelopment())
|
||||
{
|
||||
app.UseSwagger();
|
||||
app.UseSwaggerUI();
|
||||
}
|
||||
|
||||
// Map all configured CQRS endpoints (both gRPC and HTTP)
|
||||
app.UseSvrntyCqrs();
|
||||
|
||||
app.Run();
|
||||
```
|
||||
|
||||
**Benefits:**
|
||||
- Single codebase supports multiple protocols
|
||||
- gRPC for high-performance, low-latency scenarios (microservices, internal APIs)
|
||||
- HTTP for web browsers, legacy clients, and public APIs
|
||||
- Same commands, queries, and validation logic for both protocols
|
||||
- Swagger UI available for HTTP endpoints, gRPC reflection for gRPC clients
|
||||
|
||||
# Fluent Validation
|
||||
|
||||
FluentValidation is optional but recommended for command and query validation. The `Svrnty.CQRS.FluentValidation` package provides extension methods to simplify validator registration.
|
||||
|
||||
## With Svrnty.CQRS.FluentValidation (Recommended)
|
||||
|
||||
The package exposes extension method overloads that accept the validator as a generic parameter:
|
||||
|
||||
```bash
|
||||
dotnet add package Svrnty.CQRS.FluentValidation
|
||||
```
|
||||
|
||||
```csharp
|
||||
using Svrnty.CQRS.FluentValidation; // Extension methods for validator registration
|
||||
|
||||
// Command with result - validator as last generic parameter
|
||||
builder.Services.AddCommand<EchoCommand, string, EchoCommandHandler, EchoCommandValidator>();
|
||||
|
||||
// Command without result - validator included in generics
|
||||
builder.Services.AddCommand<CreatePersonCommand, CreatePersonCommandHandler, CreatePersonCommandValidator>();
|
||||
```
|
||||
|
||||
**Benefits:**
|
||||
- **Single line registration** - Handler and validator registered together
|
||||
- **Type safety** - Compiler ensures validator matches command type
|
||||
- **Less boilerplate** - No need for separate `AddTransient<IValidator<T>>()` calls
|
||||
- **Cleaner code** - Clear intent that validation is part of command pipeline
|
||||
|
||||
## Without Svrnty.CQRS.FluentValidation
|
||||
|
||||
If you prefer not to use the FluentValidation package, you need to register commands and validators separately:
|
||||
|
||||
```csharp
|
||||
using FluentValidation;
|
||||
using Svrnty.CQRS;
|
||||
|
||||
// Register command handler
|
||||
builder.Services.AddCommand<EchoCommand, string, EchoCommandHandler>();
|
||||
|
||||
// Manually register validator
|
||||
builder.Services.AddTransient<IValidator<EchoCommand>, EchoCommandValidator>();
|
||||
```
|
||||
|
||||
# 2024-2025 Roadmap
|
||||
|
||||
| Task | Description | Status |
|
||||
|----------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------|--------|
|
||||
| Support .NET 10 | .NET 10 with C# 14 language support. | ✅ |
|
||||
| Update FluentValidation | Upgrade FluentValidation to version 11.x for .NET 10 compatibility. | ✅ |
|
||||
| Add gRPC Support with source generators | Implement gRPC endpoints with source generators and Google Rich Error Model for validation. | ✅ |
|
||||
| Create a demo project (Svrnty.CQRS.Grpc.Sample) | Develop a comprehensive demo project showcasing gRPC and HTTP endpoints. | ✅ |
|
||||
| Create a website for the Framework | Develop a website to host comprehensive documentation for the framework. | ⬜️ |
|
||||
|
||||
# 2026 Roadmap
|
||||
|
||||
| Task | Description | Status |
|
||||
|----------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------|--------|
|
||||
| gRPC Compression Support | Smart message compression with automatic threshold detection and per-handler control. | ⬜️ |
|
||||
| gRPC Metadata & Authorization Support | Expose ServerCallContext to handlers and integrate authorization services for gRPC endpoints. | ⬜️ |
|
||||
MIT OR Apache-2.0
|
||||
|
||||
Reference in New Issue
Block a user