@corbat-tech/coding-standards-mcp 1.0.3 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +233 -337
- package/dist/agent.d.ts +5 -6
- package/dist/agent.d.ts.map +1 -1
- package/dist/agent.js +95 -217
- package/dist/agent.js.map +1 -1
- package/dist/analysis/code-analyzer.d.ts +44 -0
- package/dist/analysis/code-analyzer.d.ts.map +1 -0
- package/dist/analysis/code-analyzer.js +528 -0
- package/dist/analysis/code-analyzer.js.map +1 -0
- package/dist/errors.d.ts +58 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +112 -0
- package/dist/errors.js.map +1 -0
- package/dist/guardrails.d.ts +35 -0
- package/dist/guardrails.d.ts.map +1 -0
- package/dist/guardrails.js +303 -0
- package/dist/guardrails.js.map +1 -0
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/logger.d.ts +36 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/logger.js +63 -0
- package/dist/logger.js.map +1 -0
- package/dist/metrics.d.ts +40 -0
- package/dist/metrics.d.ts.map +1 -0
- package/dist/metrics.js +97 -0
- package/dist/metrics.js.map +1 -0
- package/dist/profiles.d.ts +1 -1
- package/dist/profiles.d.ts.map +1 -1
- package/dist/profiles.js +239 -108
- package/dist/profiles.js.map +1 -1
- package/dist/prompts.js +1 -1
- package/dist/prompts.js.map +1 -1
- package/dist/tools/definitions.d.ts +143 -0
- package/dist/tools/definitions.d.ts.map +1 -0
- package/dist/tools/definitions.js +229 -0
- package/dist/tools/definitions.js.map +1 -0
- package/dist/tools/handlers/get-context.d.ts +12 -0
- package/dist/tools/handlers/get-context.d.ts.map +1 -0
- package/dist/tools/handlers/get-context.js +233 -0
- package/dist/tools/handlers/get-context.js.map +1 -0
- package/dist/tools/handlers/health.d.ts +11 -0
- package/dist/tools/handlers/health.d.ts.map +1 -0
- package/dist/tools/handlers/health.js +57 -0
- package/dist/tools/handlers/health.js.map +1 -0
- package/dist/tools/handlers/index.d.ts +12 -0
- package/dist/tools/handlers/index.d.ts.map +1 -0
- package/dist/tools/handlers/index.js +12 -0
- package/dist/tools/handlers/index.js.map +1 -0
- package/dist/tools/handlers/init.d.ts +12 -0
- package/dist/tools/handlers/init.d.ts.map +1 -0
- package/dist/tools/handlers/init.js +102 -0
- package/dist/tools/handlers/init.js.map +1 -0
- package/dist/tools/handlers/profiles.d.ts +11 -0
- package/dist/tools/handlers/profiles.d.ts.map +1 -0
- package/dist/tools/handlers/profiles.js +25 -0
- package/dist/tools/handlers/profiles.js.map +1 -0
- package/dist/tools/handlers/search.d.ts +12 -0
- package/dist/tools/handlers/search.d.ts.map +1 -0
- package/dist/tools/handlers/search.js +58 -0
- package/dist/tools/handlers/search.js.map +1 -0
- package/dist/tools/handlers/validate.d.ts +15 -0
- package/dist/tools/handlers/validate.d.ts.map +1 -0
- package/dist/tools/handlers/validate.js +71 -0
- package/dist/tools/handlers/validate.js.map +1 -0
- package/dist/tools/handlers/verify.d.ts +38 -0
- package/dist/tools/handlers/verify.d.ts.map +1 -0
- package/dist/tools/handlers/verify.js +172 -0
- package/dist/tools/handlers/verify.js.map +1 -0
- package/dist/tools/index.d.ts +22 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +75 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/schemas.d.ts +29 -0
- package/dist/tools/schemas.d.ts.map +1 -0
- package/dist/tools/schemas.js +20 -0
- package/dist/tools/schemas.js.map +1 -0
- package/dist/tools.js +2 -2
- package/dist/tools.js.map +1 -1
- package/dist/types.d.ts +141 -71
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +92 -40
- package/dist/types.js.map +1 -1
- package/package.json +2 -2
- package/profiles/examples/microservice-kafka.yaml +122 -0
- package/profiles/examples/startup-fast.yaml +67 -0
- package/profiles/examples/strict-enterprise.yaml +62 -0
- package/profiles/templates/angular.yaml +614 -0
- package/profiles/templates/csharp-dotnet.yaml +529 -0
- package/profiles/templates/flutter.yaml +547 -0
- package/profiles/templates/go.yaml +1276 -0
- package/profiles/templates/java-spring-backend.yaml +326 -0
- package/profiles/templates/kotlin-spring.yaml +417 -0
- package/profiles/templates/nextjs.yaml +536 -0
- package/profiles/templates/nodejs.yaml +594 -0
- package/profiles/templates/python.yaml +546 -0
- package/profiles/templates/react.yaml +456 -0
- package/profiles/templates/rust.yaml +508 -0
- package/profiles/templates/vue.yaml +483 -0
|
@@ -0,0 +1,529 @@
|
|
|
1
|
+
# ============================================================================
|
|
2
|
+
# CORBAT MCP - C# + ASP.NET Core Profile
|
|
3
|
+
# ============================================================================
|
|
4
|
+
# Production-ready standards for C# ASP.NET Core backend applications.
|
|
5
|
+
# Based on Microsoft guidelines, Clean Architecture, and modern C# features.
|
|
6
|
+
# ============================================================================
|
|
7
|
+
|
|
8
|
+
name: "C# ASP.NET Core Standards"
|
|
9
|
+
description: "Production-ready standards for C# ASP.NET Core with Clean Architecture, CQRS, and modern C# 12 features"
|
|
10
|
+
|
|
11
|
+
# ----------------------------------------------------------------------------
|
|
12
|
+
# ARCHITECTURE
|
|
13
|
+
# ----------------------------------------------------------------------------
|
|
14
|
+
architecture:
|
|
15
|
+
type: clean
|
|
16
|
+
enforceLayerDependencies: true
|
|
17
|
+
layers:
|
|
18
|
+
- name: Domain
|
|
19
|
+
description: "Core business logic. Contains entities, value objects, aggregates, and domain events. No external dependencies."
|
|
20
|
+
allowedDependencies: []
|
|
21
|
+
projects:
|
|
22
|
+
- "*.Domain"
|
|
23
|
+
namespaces:
|
|
24
|
+
- "*.Domain.Entities"
|
|
25
|
+
- "*.Domain.ValueObjects"
|
|
26
|
+
- "*.Domain.Events"
|
|
27
|
+
- "*.Domain.Exceptions"
|
|
28
|
+
- "*.Domain.Interfaces"
|
|
29
|
+
|
|
30
|
+
- name: Application
|
|
31
|
+
description: "Use cases and application services. Contains commands, queries, handlers, and DTOs."
|
|
32
|
+
allowedDependencies:
|
|
33
|
+
- Domain
|
|
34
|
+
projects:
|
|
35
|
+
- "*.Application"
|
|
36
|
+
namespaces:
|
|
37
|
+
- "*.Application.Commands"
|
|
38
|
+
- "*.Application.Queries"
|
|
39
|
+
- "*.Application.Handlers"
|
|
40
|
+
- "*.Application.DTOs"
|
|
41
|
+
- "*.Application.Interfaces"
|
|
42
|
+
|
|
43
|
+
- name: Infrastructure
|
|
44
|
+
description: "External concerns: database, external APIs, messaging, caching."
|
|
45
|
+
allowedDependencies:
|
|
46
|
+
- Domain
|
|
47
|
+
- Application
|
|
48
|
+
projects:
|
|
49
|
+
- "*.Infrastructure"
|
|
50
|
+
namespaces:
|
|
51
|
+
- "*.Infrastructure.Persistence"
|
|
52
|
+
- "*.Infrastructure.Services"
|
|
53
|
+
- "*.Infrastructure.Messaging"
|
|
54
|
+
|
|
55
|
+
- name: WebApi
|
|
56
|
+
description: "API layer: controllers, filters, middleware."
|
|
57
|
+
allowedDependencies:
|
|
58
|
+
- Domain
|
|
59
|
+
- Application
|
|
60
|
+
- Infrastructure
|
|
61
|
+
projects:
|
|
62
|
+
- "*.WebApi"
|
|
63
|
+
- "*.Api"
|
|
64
|
+
namespaces:
|
|
65
|
+
- "*.WebApi.Controllers"
|
|
66
|
+
- "*.WebApi.Filters"
|
|
67
|
+
- "*.WebApi.Middleware"
|
|
68
|
+
|
|
69
|
+
architectureTests:
|
|
70
|
+
tool: "NetArchTest"
|
|
71
|
+
enabled: true
|
|
72
|
+
rules:
|
|
73
|
+
- "Domain should not reference Application"
|
|
74
|
+
- "Domain should not reference Infrastructure"
|
|
75
|
+
- "Application should not reference Infrastructure"
|
|
76
|
+
- "Domain should not reference WebApi"
|
|
77
|
+
|
|
78
|
+
# ----------------------------------------------------------------------------
|
|
79
|
+
# C# FEATURES (C# 12)
|
|
80
|
+
# ----------------------------------------------------------------------------
|
|
81
|
+
csharpFeatures:
|
|
82
|
+
version: "12"
|
|
83
|
+
|
|
84
|
+
nullableReferenceTypes:
|
|
85
|
+
enabled: true
|
|
86
|
+
treatWarningsAsErrors: true
|
|
87
|
+
annotations: true
|
|
88
|
+
analysis: true
|
|
89
|
+
|
|
90
|
+
records:
|
|
91
|
+
useForDTOs: true
|
|
92
|
+
useForValueObjects: true
|
|
93
|
+
useForCommands: true
|
|
94
|
+
useForQueries: true
|
|
95
|
+
examples:
|
|
96
|
+
- "public record CreateOrderCommand(Guid CustomerId, List<OrderItem> Items);"
|
|
97
|
+
- "public record OrderResponse(Guid Id, string Status, decimal Total);"
|
|
98
|
+
- "public record Money(decimal Amount, string Currency);"
|
|
99
|
+
|
|
100
|
+
primaryConstructors:
|
|
101
|
+
useForDI: true
|
|
102
|
+
useForRecords: true
|
|
103
|
+
example: |
|
|
104
|
+
public class OrderService(
|
|
105
|
+
IOrderRepository repository,
|
|
106
|
+
ILogger<OrderService> logger)
|
|
107
|
+
{
|
|
108
|
+
public async Task<Order> GetAsync(OrderId id) => ...
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
patternMatching:
|
|
112
|
+
useSwitch: true
|
|
113
|
+
useIsPattern: true
|
|
114
|
+
usePropertyPattern: true
|
|
115
|
+
examples:
|
|
116
|
+
- |
|
|
117
|
+
return order.Status switch
|
|
118
|
+
{
|
|
119
|
+
OrderStatus.Pending => HandlePending(order),
|
|
120
|
+
OrderStatus.Confirmed => HandleConfirmed(order),
|
|
121
|
+
OrderStatus.Shipped { TrackingNumber: var tn } => HandleShipped(order, tn),
|
|
122
|
+
_ => throw new InvalidOperationException()
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
fileScopedNamespaces: true
|
|
126
|
+
implicitUsings: true
|
|
127
|
+
rawStringLiterals: true
|
|
128
|
+
requiredMembers: true
|
|
129
|
+
initOnlySetters: true
|
|
130
|
+
|
|
131
|
+
# ----------------------------------------------------------------------------
|
|
132
|
+
# CQRS + MEDIATR
|
|
133
|
+
# ----------------------------------------------------------------------------
|
|
134
|
+
cqrs:
|
|
135
|
+
enabled: true
|
|
136
|
+
library: "MediatR"
|
|
137
|
+
separation: "logical"
|
|
138
|
+
|
|
139
|
+
patterns:
|
|
140
|
+
commands:
|
|
141
|
+
suffix: "Command"
|
|
142
|
+
handler: "CommandHandler"
|
|
143
|
+
returnType: "Result<T>"
|
|
144
|
+
example: |
|
|
145
|
+
public record CreateOrderCommand(
|
|
146
|
+
Guid CustomerId,
|
|
147
|
+
List<OrderItemDto> Items
|
|
148
|
+
) : IRequest<Result<OrderId>>;
|
|
149
|
+
|
|
150
|
+
public class CreateOrderCommandHandler(
|
|
151
|
+
IOrderRepository repository,
|
|
152
|
+
IUnitOfWork unitOfWork)
|
|
153
|
+
: IRequestHandler<CreateOrderCommand, Result<OrderId>>
|
|
154
|
+
{
|
|
155
|
+
public async Task<Result<OrderId>> Handle(
|
|
156
|
+
CreateOrderCommand request,
|
|
157
|
+
CancellationToken cancellationToken)
|
|
158
|
+
{
|
|
159
|
+
// Implementation
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
queries:
|
|
164
|
+
suffix: "Query"
|
|
165
|
+
handler: "QueryHandler"
|
|
166
|
+
returnType: "Result<T>"
|
|
167
|
+
example: |
|
|
168
|
+
public record GetOrderByIdQuery(Guid OrderId) : IRequest<Result<OrderResponse>>;
|
|
169
|
+
|
|
170
|
+
behaviors:
|
|
171
|
+
- "ValidationBehavior"
|
|
172
|
+
- "LoggingBehavior"
|
|
173
|
+
- "TransactionBehavior"
|
|
174
|
+
|
|
175
|
+
# ----------------------------------------------------------------------------
|
|
176
|
+
# CODE QUALITY
|
|
177
|
+
# ----------------------------------------------------------------------------
|
|
178
|
+
codeQuality:
|
|
179
|
+
maxMethodLines: 25
|
|
180
|
+
maxClassLines: 200
|
|
181
|
+
maxFileLines: 400
|
|
182
|
+
maxMethodParameters: 4
|
|
183
|
+
maxCyclomaticComplexity: 10
|
|
184
|
+
requireDocumentation: true
|
|
185
|
+
requireTests: true
|
|
186
|
+
minimumTestCoverage: 80
|
|
187
|
+
|
|
188
|
+
principles:
|
|
189
|
+
- "SOLID principles"
|
|
190
|
+
- "DRY (Don't Repeat Yourself)"
|
|
191
|
+
- "Prefer composition over inheritance"
|
|
192
|
+
- "Depend on abstractions, not concretions"
|
|
193
|
+
- "Fail fast"
|
|
194
|
+
- "Make illegal states unrepresentable"
|
|
195
|
+
|
|
196
|
+
analyzers:
|
|
197
|
+
- "Microsoft.CodeAnalysis.NetAnalyzers"
|
|
198
|
+
- "StyleCop.Analyzers"
|
|
199
|
+
- "SonarAnalyzer.CSharp"
|
|
200
|
+
- "Roslynator.Analyzers"
|
|
201
|
+
|
|
202
|
+
editorconfig:
|
|
203
|
+
enabled: true
|
|
204
|
+
treatWarningsAsErrors: true
|
|
205
|
+
|
|
206
|
+
# ----------------------------------------------------------------------------
|
|
207
|
+
# NAMING CONVENTIONS
|
|
208
|
+
# ----------------------------------------------------------------------------
|
|
209
|
+
naming:
|
|
210
|
+
general:
|
|
211
|
+
class: PascalCase
|
|
212
|
+
interface: IPascalCase
|
|
213
|
+
method: PascalCase
|
|
214
|
+
property: PascalCase
|
|
215
|
+
field: _camelCase
|
|
216
|
+
parameter: camelCase
|
|
217
|
+
constant: PascalCase
|
|
218
|
+
namespace: PascalCase.Dot.Separated
|
|
219
|
+
file: PascalCase.cs
|
|
220
|
+
|
|
221
|
+
suffixes:
|
|
222
|
+
controller: "Controller"
|
|
223
|
+
service: "Service"
|
|
224
|
+
repository: "Repository"
|
|
225
|
+
handler: "Handler"
|
|
226
|
+
validator: "Validator"
|
|
227
|
+
mapper: "Mapper"
|
|
228
|
+
dto: "Dto|Request|Response"
|
|
229
|
+
exception: "Exception"
|
|
230
|
+
configuration: "Configuration"
|
|
231
|
+
options: "Options"
|
|
232
|
+
|
|
233
|
+
testing:
|
|
234
|
+
testClass: "Tests"
|
|
235
|
+
integrationTest: "IntegrationTests"
|
|
236
|
+
testMethod: "MethodName_Scenario_ExpectedResult"
|
|
237
|
+
fixture: "Fixture"
|
|
238
|
+
|
|
239
|
+
# ----------------------------------------------------------------------------
|
|
240
|
+
# TESTING
|
|
241
|
+
# ----------------------------------------------------------------------------
|
|
242
|
+
testing:
|
|
243
|
+
framework: "xUnit"
|
|
244
|
+
assertionLibrary: "FluentAssertions"
|
|
245
|
+
mockingLibrary: "NSubstitute"
|
|
246
|
+
|
|
247
|
+
types:
|
|
248
|
+
unit:
|
|
249
|
+
suffix: "Tests"
|
|
250
|
+
location: "tests/UnitTests"
|
|
251
|
+
coverage: 80
|
|
252
|
+
patterns:
|
|
253
|
+
- "Arrange-Act-Assert"
|
|
254
|
+
- "Given-When-Then"
|
|
255
|
+
|
|
256
|
+
integration:
|
|
257
|
+
suffix: "IntegrationTests"
|
|
258
|
+
location: "tests/IntegrationTests"
|
|
259
|
+
useWebApplicationFactory: true
|
|
260
|
+
useTestcontainers: true
|
|
261
|
+
useRespawn: true
|
|
262
|
+
|
|
263
|
+
architecture:
|
|
264
|
+
tool: "NetArchTest"
|
|
265
|
+
location: "tests/ArchitectureTests"
|
|
266
|
+
|
|
267
|
+
patterns:
|
|
268
|
+
fluentAssertions: true
|
|
269
|
+
nsubstitute: true
|
|
270
|
+
autoFixture: true
|
|
271
|
+
bogus: true
|
|
272
|
+
example: |
|
|
273
|
+
[Fact]
|
|
274
|
+
public async Task CreateOrder_WithValidItems_ReturnsOrderId()
|
|
275
|
+
{
|
|
276
|
+
// Arrange
|
|
277
|
+
var command = new CreateOrderCommand(
|
|
278
|
+
CustomerId: Guid.NewGuid(),
|
|
279
|
+
Items: [new OrderItemDto("SKU-001", 2)]
|
|
280
|
+
);
|
|
281
|
+
|
|
282
|
+
_orderRepository
|
|
283
|
+
.AddAsync(Arg.Any<Order>())
|
|
284
|
+
.Returns(Task.CompletedTask);
|
|
285
|
+
|
|
286
|
+
// Act
|
|
287
|
+
var result = await _handler.Handle(command, CancellationToken.None);
|
|
288
|
+
|
|
289
|
+
// Assert
|
|
290
|
+
result.IsSuccess.Should().BeTrue();
|
|
291
|
+
result.Value.Should().NotBeEmpty();
|
|
292
|
+
await _orderRepository.Received(1).AddAsync(Arg.Any<Order>());
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
testcontainers:
|
|
296
|
+
enabled: true
|
|
297
|
+
containers:
|
|
298
|
+
- "PostgreSQL"
|
|
299
|
+
- "SqlServer"
|
|
300
|
+
- "Redis"
|
|
301
|
+
- "RabbitMQ"
|
|
302
|
+
|
|
303
|
+
# ----------------------------------------------------------------------------
|
|
304
|
+
# VALIDATION
|
|
305
|
+
# ----------------------------------------------------------------------------
|
|
306
|
+
validation:
|
|
307
|
+
library: "FluentValidation"
|
|
308
|
+
integration: "MediatR pipeline"
|
|
309
|
+
|
|
310
|
+
patterns:
|
|
311
|
+
commandValidation: true
|
|
312
|
+
dtoValidation: true
|
|
313
|
+
domainValidation: true
|
|
314
|
+
example: |
|
|
315
|
+
public class CreateOrderCommandValidator : AbstractValidator<CreateOrderCommand>
|
|
316
|
+
{
|
|
317
|
+
public CreateOrderCommandValidator()
|
|
318
|
+
{
|
|
319
|
+
RuleFor(x => x.CustomerId).NotEmpty();
|
|
320
|
+
RuleFor(x => x.Items).NotEmpty();
|
|
321
|
+
RuleForEach(x => x.Items).ChildRules(item =>
|
|
322
|
+
{
|
|
323
|
+
item.RuleFor(i => i.Quantity).GreaterThan(0);
|
|
324
|
+
});
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
# ----------------------------------------------------------------------------
|
|
329
|
+
# ERROR HANDLING
|
|
330
|
+
# ----------------------------------------------------------------------------
|
|
331
|
+
errorHandling:
|
|
332
|
+
format: "RFC 7807 Problem Details"
|
|
333
|
+
globalHandler: "ExceptionMiddleware"
|
|
334
|
+
|
|
335
|
+
resultPattern:
|
|
336
|
+
enabled: true
|
|
337
|
+
library: "FluentResults or Ardalis.Result"
|
|
338
|
+
example: |
|
|
339
|
+
public async Task<Result<Order>> GetOrderAsync(OrderId id)
|
|
340
|
+
{
|
|
341
|
+
var order = await _repository.GetByIdAsync(id);
|
|
342
|
+
if (order is null)
|
|
343
|
+
return Result.Fail<Order>($"Order {id} not found");
|
|
344
|
+
|
|
345
|
+
return Result.Ok(order);
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
customExceptions:
|
|
349
|
+
domain:
|
|
350
|
+
- "DomainException"
|
|
351
|
+
- "EntityNotFoundException"
|
|
352
|
+
- "BusinessRuleViolationException"
|
|
353
|
+
application:
|
|
354
|
+
- "ValidationException"
|
|
355
|
+
- "UnauthorizedException"
|
|
356
|
+
|
|
357
|
+
problemDetails:
|
|
358
|
+
enabled: true
|
|
359
|
+
includeExceptionDetails: "Development only"
|
|
360
|
+
|
|
361
|
+
# ----------------------------------------------------------------------------
|
|
362
|
+
# OBSERVABILITY
|
|
363
|
+
# ----------------------------------------------------------------------------
|
|
364
|
+
observability:
|
|
365
|
+
enabled: true
|
|
366
|
+
|
|
367
|
+
logging:
|
|
368
|
+
framework: "Serilog"
|
|
369
|
+
format: "JSON"
|
|
370
|
+
structuredLogging: true
|
|
371
|
+
enrichers:
|
|
372
|
+
- "FromLogContext"
|
|
373
|
+
- "WithMachineName"
|
|
374
|
+
- "WithEnvironmentName"
|
|
375
|
+
sinks:
|
|
376
|
+
- "Console"
|
|
377
|
+
- "Seq"
|
|
378
|
+
- "ApplicationInsights"
|
|
379
|
+
example: |
|
|
380
|
+
Log.Information(
|
|
381
|
+
"Processing order {OrderId} for customer {CustomerId}",
|
|
382
|
+
order.Id,
|
|
383
|
+
order.CustomerId);
|
|
384
|
+
|
|
385
|
+
metrics:
|
|
386
|
+
framework: "OpenTelemetry"
|
|
387
|
+
exporters:
|
|
388
|
+
- "Prometheus"
|
|
389
|
+
- "ApplicationInsights"
|
|
390
|
+
|
|
391
|
+
tracing:
|
|
392
|
+
framework: "OpenTelemetry"
|
|
393
|
+
propagation: "W3C"
|
|
394
|
+
exporters:
|
|
395
|
+
- "Jaeger"
|
|
396
|
+
- "ApplicationInsights"
|
|
397
|
+
|
|
398
|
+
healthChecks:
|
|
399
|
+
library: "AspNetCore.HealthChecks"
|
|
400
|
+
endpoints:
|
|
401
|
+
- "/health"
|
|
402
|
+
- "/health/ready"
|
|
403
|
+
- "/health/live"
|
|
404
|
+
checks:
|
|
405
|
+
- "Database"
|
|
406
|
+
- "Redis"
|
|
407
|
+
- "RabbitMQ"
|
|
408
|
+
- "External APIs"
|
|
409
|
+
|
|
410
|
+
# ----------------------------------------------------------------------------
|
|
411
|
+
# DATABASE
|
|
412
|
+
# ----------------------------------------------------------------------------
|
|
413
|
+
database:
|
|
414
|
+
orm: "Entity Framework Core"
|
|
415
|
+
|
|
416
|
+
patterns:
|
|
417
|
+
repository: true
|
|
418
|
+
unitOfWork: true
|
|
419
|
+
specification: true
|
|
420
|
+
softDelete: true
|
|
421
|
+
|
|
422
|
+
migrations:
|
|
423
|
+
tool: "EF Core Migrations"
|
|
424
|
+
location: "Infrastructure/Persistence/Migrations"
|
|
425
|
+
|
|
426
|
+
configuration:
|
|
427
|
+
approach: "Fluent API"
|
|
428
|
+
location: "Infrastructure/Persistence/Configurations"
|
|
429
|
+
|
|
430
|
+
queryOptimization:
|
|
431
|
+
splitQueries: true
|
|
432
|
+
noTracking: true
|
|
433
|
+
projections: true
|
|
434
|
+
example: |
|
|
435
|
+
public async Task<Order?> GetByIdAsync(OrderId id)
|
|
436
|
+
{
|
|
437
|
+
return await _context.Orders
|
|
438
|
+
.AsNoTracking()
|
|
439
|
+
.Include(o => o.Items)
|
|
440
|
+
.AsSplitQuery()
|
|
441
|
+
.FirstOrDefaultAsync(o => o.Id == id);
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
# ----------------------------------------------------------------------------
|
|
445
|
+
# API DESIGN
|
|
446
|
+
# ----------------------------------------------------------------------------
|
|
447
|
+
apiDesign:
|
|
448
|
+
approach: "Minimal APIs or Controllers"
|
|
449
|
+
|
|
450
|
+
minimalApis:
|
|
451
|
+
enabled: true
|
|
452
|
+
grouping: true
|
|
453
|
+
example: |
|
|
454
|
+
app.MapGroup("/api/orders")
|
|
455
|
+
.MapOrderEndpoints()
|
|
456
|
+
.RequireAuthorization()
|
|
457
|
+
.WithTags("Orders");
|
|
458
|
+
|
|
459
|
+
controllers:
|
|
460
|
+
baseClass: "ControllerBase"
|
|
461
|
+
attributes:
|
|
462
|
+
- "[ApiController]"
|
|
463
|
+
- "[Route(\"api/[controller]\")]"
|
|
464
|
+
|
|
465
|
+
versioning:
|
|
466
|
+
enabled: true
|
|
467
|
+
strategy: "URL path (/api/v1/)"
|
|
468
|
+
|
|
469
|
+
documentation:
|
|
470
|
+
tool: "Swashbuckle or NSwag"
|
|
471
|
+
xmlComments: true
|
|
472
|
+
|
|
473
|
+
# ----------------------------------------------------------------------------
|
|
474
|
+
# DEPENDENCY INJECTION
|
|
475
|
+
# ----------------------------------------------------------------------------
|
|
476
|
+
dependencyInjection:
|
|
477
|
+
container: "Microsoft.Extensions.DependencyInjection"
|
|
478
|
+
|
|
479
|
+
patterns:
|
|
480
|
+
scrutor: true
|
|
481
|
+
decorators: true
|
|
482
|
+
factories: true
|
|
483
|
+
example: |
|
|
484
|
+
services.Scan(scan => scan
|
|
485
|
+
.FromAssemblyOf<ApplicationAssemblyMarker>()
|
|
486
|
+
.AddClasses(classes => classes.AssignableTo(typeof(IRequestHandler<,>)))
|
|
487
|
+
.AsImplementedInterfaces()
|
|
488
|
+
.WithScopedLifetime());
|
|
489
|
+
|
|
490
|
+
lifetimes:
|
|
491
|
+
singleton: "Stateless services, caches"
|
|
492
|
+
scoped: "DbContext, repositories, unit of work"
|
|
493
|
+
transient: "Lightweight, stateless"
|
|
494
|
+
|
|
495
|
+
# ----------------------------------------------------------------------------
|
|
496
|
+
# TECHNOLOGIES
|
|
497
|
+
# ----------------------------------------------------------------------------
|
|
498
|
+
technologies:
|
|
499
|
+
- name: csharp
|
|
500
|
+
version: "12"
|
|
501
|
+
specificRules:
|
|
502
|
+
useNullableReferenceTypes: true
|
|
503
|
+
useRecords: true
|
|
504
|
+
usePrimaryConstructors: true
|
|
505
|
+
usePatternMatching: true
|
|
506
|
+
useFileScopedNamespaces: true
|
|
507
|
+
|
|
508
|
+
- name: aspnetcore
|
|
509
|
+
version: "8.0"
|
|
510
|
+
specificRules:
|
|
511
|
+
useMinimalApis: true
|
|
512
|
+
useProblemDetails: true
|
|
513
|
+
useEndpointFilters: true
|
|
514
|
+
useOutputCaching: true
|
|
515
|
+
|
|
516
|
+
- name: efcore
|
|
517
|
+
version: "8.0"
|
|
518
|
+
specificRules:
|
|
519
|
+
useAsNoTracking: true
|
|
520
|
+
useSplitQueries: true
|
|
521
|
+
useCompiledQueries: true
|
|
522
|
+
|
|
523
|
+
- name: testing
|
|
524
|
+
specificRules:
|
|
525
|
+
useXUnit: true
|
|
526
|
+
useFluentAssertions: true
|
|
527
|
+
useNSubstitute: true
|
|
528
|
+
useTestcontainers: true
|
|
529
|
+
useRespawn: true
|