- Add path-specific rules for commands/queries, dynamic queries, validation, and gRPC - Add /add-command, /add-query, /add-dynamic-query scaffolding skills - Add project settings with post-edit formatting, proto validation, and build-gate hooks - Add .editorconfig codifying existing code style conventions - Trim CLAUDE.md from 414 to 130 lines (domain details moved to rules) - Add .harness-version tracking for the shared claude-harness repo Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
110 lines
3.2 KiB
Markdown
110 lines
3.2 KiB
Markdown
---
|
|
paths:
|
|
- "**/*.proto"
|
|
- "**/Protos/**"
|
|
- "*Grpc*"
|
|
---
|
|
|
|
# gRPC Integration
|
|
|
|
## Proto File Conventions
|
|
|
|
Proto files live in `Protos/` directory. The source generator (`Svrnty.CQRS.Grpc.Generators`) auto-generates service implementations at compile time.
|
|
|
|
### Service Structure
|
|
```protobuf
|
|
service CommandService {
|
|
rpc PlaceOrder (PlaceOrderCommandRequest) returns (PlaceOrderCommandResponse);
|
|
}
|
|
|
|
service QueryService {
|
|
rpc FetchUserById (FetchUserByIdQueryRequest) returns (FetchUserByIdQueryResponse);
|
|
}
|
|
|
|
service DynamicQueryService {
|
|
rpc QueryOrders (DynamicQueryOrdersRequest) returns (DynamicQueryOrdersResponse);
|
|
}
|
|
```
|
|
|
|
### Naming Rules
|
|
- RPC method name: command/query name without the `Command`/`Query` suffix
|
|
- Request message: `{Name}CommandRequest` or `{Name}QueryRequest`
|
|
- Response message: `{Name}CommandResponse` or `{Name}QueryResponse`
|
|
- Dynamic query request: `DynamicQuery{PluralEntity}Request`
|
|
- Dynamic query response: `DynamicQuery{PluralEntity}Response`
|
|
- Fields use `snake_case` (proto convention), mapped case-insensitively to C# `PascalCase` properties
|
|
|
|
### Field Mapping
|
|
C# property names must match proto field names (case-insensitive):
|
|
|
|
| C# Property | Proto Field |
|
|
|---------------|-----------------|
|
|
| `UserId` | `user_id` |
|
|
| `Name` | `name` |
|
|
| `EmailAddress`| `email_address` |
|
|
| `OrderItems` | `order_items` |
|
|
|
|
### Type Mapping
|
|
| C# | Proto |
|
|
|-------------|-------------|
|
|
| `int` | `int32` |
|
|
| `long` | `int64` |
|
|
| `string` | `string` |
|
|
| `bool` | `bool` |
|
|
| `double` | `double` |
|
|
| `float` | `float` |
|
|
| `List<T>` | `repeated T`|
|
|
| complex type| `message` |
|
|
|
|
### Dynamic Query Messages (standard, reuse across entities)
|
|
```protobuf
|
|
message DynamicQueryFilter {
|
|
string path = 1;
|
|
int32 type = 2; // PoweredSoft.DynamicQuery.Core.FilterType
|
|
string value = 3;
|
|
repeated DynamicQueryFilter and = 4;
|
|
repeated DynamicQueryFilter or = 5;
|
|
}
|
|
|
|
message DynamicQuerySort {
|
|
string path = 1;
|
|
bool ascending = 2;
|
|
}
|
|
|
|
message DynamicQueryGroup {
|
|
string path = 1;
|
|
}
|
|
|
|
message DynamicQueryAggregate {
|
|
string path = 1;
|
|
int32 type = 2; // PoweredSoft.DynamicQuery.Core.AggregateType
|
|
}
|
|
```
|
|
|
|
## Source Generator Behavior
|
|
|
|
The generator in `Svrnty.CQRS.Grpc.Generators` auto-creates:
|
|
- `CommandServiceImpl` — implements `CommandService.CommandServiceBase`
|
|
- `QueryServiceImpl` — implements `QueryService.QueryServiceBase`
|
|
- `DynamicQueryServiceImpl` — implements `DynamicQueryService.DynamicQueryServiceBase`
|
|
- `GrpcServiceRegistration` — auto-registration code
|
|
|
|
Generated implementations handle:
|
|
1. Request-to-POCO property mapping
|
|
2. Validator invocation (if registered) with Google Rich Error Model errors
|
|
3. Handler invocation with proper `CancellationToken`
|
|
4. DI scope management via `IServiceScopeFactory`
|
|
|
|
## Validation in gRPC
|
|
|
|
Validation errors return `google.rpc.Status` with `BadRequest` detail containing `FieldViolations`. This is automatic — do not manually validate in handlers.
|
|
|
|
## Registration
|
|
|
|
```csharp
|
|
builder.Services.AddSvrntyCqrs(cqrs =>
|
|
{
|
|
cqrs.AddGrpc(grpc => grpc.EnableReflection()); // reflection for grpcurl/grpcui
|
|
});
|
|
```
|