@polymorphism-tech/morph-spec 4.6.0 → 4.7.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 +394 -700
- package/docs/ARCHITECTURE.md +331 -0
- package/docs/CHEATSHEET.md +221 -0
- package/docs/COMMAND-FLOWS.md +368 -0
- package/docs/QUICKSTART.md +212 -0
- package/docs/examples/order-management/contracts.cs +84 -0
- package/docs/examples/order-management/proposal.md +24 -0
- package/docs/examples/order-management/spec.md +162 -0
- package/docs/plans/2026-02-23-ddd-architecture-refactor.md +1153 -0
- package/docs/plans/2026-02-23-ddd-nextsteps.md +682 -0
- package/docs/plans/2026-02-23-infra-architect-refactor.md +437 -0
- package/docs/plans/2026-02-23-nextjs-code-review-design.md +156 -0
- package/docs/plans/2026-02-23-nextjs-code-review-impl.md +1254 -0
- package/docs/plans/2026-02-23-nextjs-standards-design.md +149 -0
- package/docs/plans/2026-02-23-nextjs-standards-impl.md +1846 -0
- package/framework/agents/README.md +14 -14
- package/framework/agents/architecture/standards-architect.md +159 -159
- package/framework/agents/frontend/nextjs-expert.md +87 -127
- package/framework/agents/infrastructure/azure-architect.md +147 -147
- package/framework/agents/infrastructure/infra-architect.md +45 -0
- package/framework/agents.json +1145 -278
- package/framework/rules/frontend-standards.md +0 -3
- package/framework/rules/nextjs-standards.md +17 -0
- package/framework/skills/level-0-meta/code-review-nextjs/SKILL.md +147 -0
- package/framework/skills/level-0-meta/code-review-nextjs/references/review-example-nextjs.md +254 -0
- package/framework/skills/level-0-meta/tool-usage-guide/SKILL.md +3 -3
- package/framework/skills/level-1-workflows/phase-design/SKILL.md +45 -9
- package/framework/skills/level-1-workflows/phase-tasks/SKILL.md +38 -0
- package/framework/standards/STANDARDS.json +121 -0
- package/framework/standards/architecture/ddd/bounded-contexts.md +105 -0
- package/framework/standards/architecture/ddd/complexity-levels.md +108 -0
- package/framework/standards/architecture/ddd/ubiquitous-language.md +58 -0
- package/framework/standards/frontend/nextjs/app-router.md +123 -0
- package/framework/standards/frontend/nextjs/components.md +132 -0
- package/framework/standards/frontend/nextjs/data-fetching.md +126 -0
- package/framework/standards/frontend/nextjs/forms.md +128 -0
- package/framework/standards/frontend/nextjs/naming-conventions.md +67 -0
- package/framework/standards/frontend/nextjs/project-structure.md +102 -0
- package/framework/standards/frontend/nextjs/state-management.md +72 -0
- package/framework/standards/frontend/nextjs/testing.md +111 -0
- package/framework/templates/REGISTRY.json +538 -142
- package/framework/templates/code/dotnet/contracts/contracts-level1.cs +69 -0
- package/framework/templates/code/dotnet/contracts/contracts-level2.cs +86 -0
- package/framework/templates/code/dotnet/contracts/contracts-level3.cs +41 -0
- package/framework/templates/docs/spec.md +49 -0
- package/framework/templates/frontend/nextjs/Dockerfile.nextjs.hbs +43 -0
- package/framework/templates/frontend/nextjs/client-component.tsx.hbs +26 -0
- package/framework/templates/frontend/nextjs/env.mjs.hbs +32 -0
- package/framework/templates/frontend/nextjs/feature-form.tsx.hbs +56 -0
- package/framework/templates/frontend/nextjs/page.tsx.hbs +22 -0
- package/framework/templates/frontend/nextjs/tsconfig.json.hbs +26 -0
- package/framework/templates/frontend/nextjs/use-feature.ts.hbs +54 -0
- package/framework/templates/project-structure/dotnet-ddd.md +70 -0
- package/framework/workflows/docs/enforcement-pipeline.md +2 -1
- package/package.json +1 -1
- package/scripts/scan-nextjs.mjs +169 -0
- package/src/commands/project/doctor.js +52 -1
- package/src/commands/project/init.js +15 -1
- package/src/commands/project/update.js +6 -1
- package/src/lib/standards/standards-context-injector.js +5 -0
- package/src/lib/validators/nextjs/index.js +6 -0
- package/src/lib/validators/nextjs/next-component-validator.js +181 -0
- package/src/lib/validators/validation-runner.js +5 -0
- package/src/utils/agents-installer.js +14 -2
- package/.morph/.morphversion +0 -5
- package/.morph/analytics/threads-log.jsonl +0 -6
- package/.morph/config/config.json +0 -8
- package/.morph/framework/agents.json +0 -948
- package/.morph/framework/standards/STANDARDS.json +0 -812
- package/.morph/framework/standards/ai-agents/blazor-ui.md +0 -364
- package/.morph/framework/standards/ai-agents/production.md +0 -415
- package/.morph/framework/standards/ai-agents/setup.md +0 -418
- package/.morph/framework/standards/ai-agents/team-orchestration.md +0 -479
- package/.morph/framework/standards/ai-agents/workflows.md +0 -354
- package/.morph/framework/standards/architecture/ddd/aggregates.md +0 -120
- package/.morph/framework/standards/architecture/ddd/entities.md +0 -99
- package/.morph/framework/standards/architecture/ddd/value-objects.md +0 -124
- package/.morph/framework/standards/backend/api/minimal-api.md +0 -494
- package/.morph/framework/standards/backend/api/rest.md +0 -492
- package/.morph/framework/standards/backend/api/validation.md +0 -88
- package/.morph/framework/standards/backend/authentication/passkeys.md +0 -428
- package/.morph/framework/standards/backend/database/ef-core.md +0 -199
- package/.morph/framework/standards/backend/database/migrations.md +0 -393
- package/.morph/framework/standards/backend/database/postgresql/database.md +0 -352
- package/.morph/framework/standards/backend/database/repository-patterns.md +0 -528
- package/.morph/framework/standards/backend/database/vector-search-rag.md +0 -541
- package/.morph/framework/standards/backend/dotnet/async.md +0 -366
- package/.morph/framework/standards/backend/dotnet/core.md +0 -117
- package/.morph/framework/standards/backend/dotnet/di.md +0 -439
- package/.morph/framework/standards/backend/dotnet/program-cs-checklist.md +0 -92
- package/.morph/framework/standards/backend/integrations/asaas/asaas-api.md +0 -216
- package/.morph/framework/standards/backend/integrations/clerk/clerk-auth.md +0 -290
- package/.morph/framework/standards/backend/integrations/hangfire/hangfire-jobs.md +0 -350
- package/.morph/framework/standards/backend/integrations/resend/resend-email.md +0 -385
- package/.morph/framework/standards/context/analytics.md +0 -96
- package/.morph/framework/standards/context/bundles.md +0 -110
- package/.morph/framework/standards/context/priming.md +0 -78
- package/.morph/framework/standards/core/architecture.md +0 -185
- package/.morph/framework/standards/core/coding.md +0 -214
- package/.morph/framework/standards/core/git-branching-strategy.md +0 -403
- package/.morph/framework/standards/core/git.md +0 -185
- package/.morph/framework/standards/core/testing.md +0 -295
- package/.morph/framework/standards/data/nosql/blob-storage.md +0 -102
- package/.morph/framework/standards/data/nosql/cache/redis.md +0 -97
- package/.morph/framework/standards/data/nosql/cosmos-db.md +0 -118
- package/.morph/framework/standards/data/vector-search/azure-ai-search.md +0 -121
- package/.morph/framework/standards/data/vector-search/rag-chunking.md +0 -104
- package/.morph/framework/standards/frontend/blazor/design-checklist.md +0 -222
- package/.morph/framework/standards/frontend/blazor/fluent-ui-setup.md +0 -595
- package/.morph/framework/standards/frontend/blazor/fluent-ui.md +0 -137
- package/.morph/framework/standards/frontend/blazor/html-conversion.md +0 -184
- package/.morph/framework/standards/frontend/blazor/lifecycle.md +0 -195
- package/.morph/framework/standards/frontend/blazor/pitfalls.md +0 -198
- package/.morph/framework/standards/frontend/blazor/state.md +0 -191
- package/.morph/framework/standards/frontend/design-system/animations.md +0 -151
- package/.morph/framework/standards/frontend/design-system/naming.md +0 -64
- package/.morph/framework/standards/frontend/nextjs/nextjs-patterns.md +0 -215
- package/.morph/framework/standards/infrastructure/azure/azure.md +0 -624
- package/.morph/framework/standards/infrastructure/azure/bicep/bicep-patterns.md +0 -422
- package/.morph/framework/standards/infrastructure/azure/devops/azure-devops-setup.md +0 -516
- package/.morph/framework/standards/infrastructure/azure/devops/local-development.md +0 -520
- package/.morph/framework/standards/infrastructure/azure/services/functions.md +0 -486
- package/.morph/framework/standards/infrastructure/azure/services/service-bus.md +0 -459
- package/.morph/framework/standards/infrastructure/azure/services/storage.md +0 -407
- package/.morph/framework/standards/infrastructure/docker/easypanel-deploy.md +0 -196
- package/.morph/framework/standards/infrastructure/supabase/mcp-setup.md +0 -252
- package/.morph/framework/standards/infrastructure/supabase/supabase-auth.md +0 -176
- package/.morph/framework/standards/infrastructure/supabase/supabase-pgvector.md +0 -169
- package/.morph/framework/standards/infrastructure/supabase/supabase-rls.md +0 -184
- package/.morph/framework/standards/infrastructure/supabase/supabase-storage.md +0 -153
- package/.morph/framework/standards/integration/api/graphql.md +0 -91
- package/.morph/framework/standards/integration/api/grpc.md +0 -114
- package/.morph/framework/standards/integration/api/rest-design.md +0 -95
- package/.morph/framework/standards/integration/event-driven/cqrs.md +0 -101
- package/.morph/framework/standards/integration/event-driven/event-sourcing.md +0 -124
- package/.morph/framework/standards/integration/event-driven/service-bus.md +0 -95
- package/.morph/framework/standards/integration/mcp/mcp-tools.md +0 -384
- package/.morph/framework/standards/observability/logging.md +0 -131
- package/.morph/framework/standards/observability/metrics.md +0 -121
- package/.morph/framework/standards/observability/monitoring.md +0 -114
- package/.morph/framework/standards/observability/tracing.md +0 -132
- package/.morph/framework/standards/workflows/parallel-execution.md +0 -112
- package/.morph/framework/standards/workflows/thread-management.md +0 -113
- package/.morph/framework/templates/.idea/morph-templates.xml +0 -92
- package/.morph/framework/templates/.vscode/morph-templates.code-snippets +0 -186
- package/.morph/framework/templates/IDE-SNIPPETS.md +0 -266
- package/.morph/framework/templates/README.md +0 -814
- package/.morph/framework/templates/REGISTRY.json +0 -1492
- package/.morph/framework/templates/code/dotnet/backend/repository.cs +0 -141
- package/.morph/framework/templates/code/dotnet/backend/service.cs +0 -139
- package/.morph/framework/templates/code/dotnet/contracts/Commands.cs +0 -74
- package/.morph/framework/templates/code/dotnet/contracts/Entities.cs +0 -25
- package/.morph/framework/templates/code/dotnet/contracts/Queries.cs +0 -74
- package/.morph/framework/templates/code/dotnet/contracts/README.md +0 -74
- package/.morph/framework/templates/code/dotnet/contracts/api-contracts.cs +0 -173
- package/.morph/framework/templates/code/dotnet/contracts/contracts.cs +0 -217
- package/.morph/framework/templates/code/dotnet/contracts/contracts.cs.hbs +0 -172
- package/.morph/framework/templates/code/dotnet/database/migration.cs +0 -83
- package/.morph/framework/templates/code/dotnet/frontend/component.razor +0 -239
- package/.morph/framework/templates/code/dotnet/jobs/agent.cs +0 -163
- package/.morph/framework/templates/code/dotnet/jobs/job.cs +0 -171
- package/.morph/framework/templates/code/dotnet/test.cs +0 -239
- package/.morph/framework/templates/code/sql/rls-policy.sql +0 -57
- package/.morph/framework/templates/code/sql/supabase-migration.sql +0 -100
- package/.morph/framework/templates/code/sql/supabase-migration.template.sql +0 -113
- package/.morph/framework/templates/code/typescript/contracts.ts +0 -168
- package/.morph/framework/templates/context/CONTEXT-FEATURE.md +0 -276
- package/.morph/framework/templates/context/CONTEXT.md +0 -181
- package/.morph/framework/templates/docs/clarifications.md +0 -253
- package/.morph/framework/templates/docs/onboarding.md +0 -123
- package/.morph/framework/templates/docs/proposal.md +0 -182
- package/.morph/framework/templates/docs/schema-analysis.md +0 -119
- package/.morph/framework/templates/docs/spec.md +0 -149
- package/.morph/framework/templates/docs/ui-components.md +0 -124
- package/.morph/framework/templates/docs/ui-design-system.md +0 -76
- package/.morph/framework/templates/docs/ui-flows.md +0 -167
- package/.morph/framework/templates/docs/ui-mockups.md +0 -98
- package/.morph/framework/templates/docs/user-stories.md +0 -34
- package/.morph/framework/templates/examples/design-system-examples.md +0 -357
- package/.morph/framework/templates/examples/spec-examples.md +0 -90
- package/.morph/framework/templates/feature/decisions.md +0 -187
- package/.morph/framework/templates/feature/recap.md +0 -146
- package/.morph/framework/templates/feature/tasks.md +0 -199
- package/.morph/framework/templates/infrastructure/azure/Dockerfile.example +0 -82
- package/.morph/framework/templates/infrastructure/azure/README.md +0 -286
- package/.morph/framework/templates/infrastructure/azure/app-insights.bicep +0 -63
- package/.morph/framework/templates/infrastructure/azure/app-service.bicep +0 -164
- package/.morph/framework/templates/infrastructure/azure/container-app-env.bicep +0 -49
- package/.morph/framework/templates/infrastructure/azure/container-app.bicep +0 -156
- package/.morph/framework/templates/infrastructure/azure/deploy-checklist.md +0 -426
- package/.morph/framework/templates/infrastructure/azure/deploy.ps1 +0 -229
- package/.morph/framework/templates/infrastructure/azure/deploy.sh +0 -208
- package/.morph/framework/templates/infrastructure/azure/key-vault.bicep +0 -91
- package/.morph/framework/templates/infrastructure/azure/main.bicep +0 -189
- package/.morph/framework/templates/infrastructure/azure/parameters.dev.json +0 -29
- package/.morph/framework/templates/infrastructure/azure/parameters.prod.json +0 -29
- package/.morph/framework/templates/infrastructure/azure/parameters.staging.json +0 -29
- package/.morph/framework/templates/infrastructure/azure/sql-database.bicep +0 -103
- package/.morph/framework/templates/infrastructure/azure/storage.bicep +0 -106
- package/.morph/framework/templates/infrastructure/docker/Dockerfile.template +0 -58
- package/.morph/framework/templates/infrastructure/docker/docker-compose.template.yml +0 -67
- package/.morph/framework/templates/infrastructure/docker/dockerfile-api.dockerfile +0 -38
- package/.morph/framework/templates/infrastructure/docker/dockerfile-web.dockerfile +0 -48
- package/.morph/framework/templates/infrastructure/docker/easypanel.template.json +0 -54
- package/.morph/framework/templates/infrastructure/github/README.md +0 -593
- package/.morph/framework/templates/infrastructure/github/actions/azure-auth/action.yml.hbs +0 -22
- package/.morph/framework/templates/infrastructure/github/actions/docker-build-push/action.yml.hbs +0 -45
- package/.morph/framework/templates/infrastructure/github/actions/health-check/action.yml.hbs +0 -27
- package/.morph/framework/templates/infrastructure/github/workflows/deploy-azure-app-service.yml.hbs +0 -61
- package/.morph/framework/templates/infrastructure/github/workflows/deploy-easypanel.yml.hbs +0 -31
- package/.morph/framework/templates/infrastructure/github/workflows/docker-build-push.yml.hbs +0 -59
- package/.morph/framework/templates/infrastructure/github/workflows/dotnet-build.yml.hbs +0 -39
- package/.morph/framework/templates/integrations/asaas-client.cs +0 -387
- package/.morph/framework/templates/integrations/asaas-webhook.cs +0 -351
- package/.morph/framework/templates/integrations/azure-identity-config.cs +0 -288
- package/.morph/framework/templates/integrations/clerk-config.cs +0 -258
- package/.morph/framework/templates/meta-prompts/fusion/fusion-agent.md +0 -76
- package/.morph/framework/templates/meta-prompts/fusion/fusion-aggregator.md +0 -100
- package/.morph/framework/templates/meta-prompts/hops/hop-retry.md +0 -78
- package/.morph/framework/templates/meta-prompts/hops/hop-validation.md +0 -97
- package/.morph/framework/templates/meta-prompts/hops/hop-wrapper.md +0 -36
- package/.morph/framework/templates/meta-prompts/parallel-workers/parallel-coordinator.md +0 -113
- package/.morph/framework/templates/meta-prompts/parallel-workers/parallel-worker.md +0 -80
- package/.morph/framework/templates/meta-prompts/squad-leaders/backend-squad.md +0 -90
- package/.morph/framework/templates/meta-prompts/squad-leaders/frontend-squad.md +0 -126
- package/.morph/framework/templates/meta-prompts/squad-leaders/squad-leader.md +0 -43
- package/.morph/framework/templates/meta-prompts/validators/checkpoint-validator.md +0 -107
- package/.morph/framework/templates/meta-prompts/validators/pre-commit-validator.md +0 -95
- package/.morph/framework/templates/saas/subscription.cs +0 -347
- package/.morph/framework/templates/saas/tenant.cs +0 -338
- package/.morph/framework/templates/state.template.json +0 -17
- package/.morph/framework/templates/ui/FluentDesignTheme.cs +0 -149
- package/.morph/framework/templates/ui/MudTheme.cs +0 -281
- package/.morph/framework/templates/ui/design-system.css +0 -226
- package/.morph/logs/tool-failures.log +0 -7
- package/.morph/memory/pre-compact-2026-02-23T15-43-03-521Z.json +0 -16
- package/.morph/state.json +0 -48
- package/framework/templates/code/dotnet/contracts/contracts.cs +0 -217
- package/framework/templates/code/dotnet/contracts/contracts.cs.hbs +0 -172
|
@@ -1,366 +0,0 @@
|
|
|
1
|
-
# .NET Async/Await Standards
|
|
2
|
-
|
|
3
|
-
> **Scope:** universal
|
|
4
|
-
> **Layer:** 0 (always load)
|
|
5
|
-
> **Keywords:** async, await, task, asynchronous, threading
|
|
6
|
-
> **Load When:** always
|
|
7
|
-
|
|
8
|
-
Asynchronous programming patterns for .NET applications
|
|
9
|
-
|
|
10
|
-
---
|
|
11
|
-
|
|
12
|
-
## Basic Patterns
|
|
13
|
-
|
|
14
|
-
### Async Method Signatures
|
|
15
|
-
|
|
16
|
-
```csharp
|
|
17
|
-
// ✅ CORRECT
|
|
18
|
-
public async Task<User> GetUserAsync(int id)
|
|
19
|
-
{
|
|
20
|
-
return await _repository.GetByIdAsync(id);
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
// ✅ CORRECT (no return value)
|
|
24
|
-
public async Task DeleteUserAsync(int id)
|
|
25
|
-
{
|
|
26
|
-
await _repository.DeleteAsync(id);
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
// ❌ WRONG (async void - only for event handlers)
|
|
30
|
-
public async void ProcessOrder(int orderId) // Don't do this!
|
|
31
|
-
{
|
|
32
|
-
await _orderService.ProcessAsync(orderId);
|
|
33
|
-
}
|
|
34
|
-
```
|
|
35
|
-
|
|
36
|
-
### Naming Convention
|
|
37
|
-
|
|
38
|
-
**All async methods MUST end with `Async` suffix**
|
|
39
|
-
|
|
40
|
-
```csharp
|
|
41
|
-
// ✅ CORRECT
|
|
42
|
-
Task<Order> GetOrderAsync(int id)
|
|
43
|
-
Task SaveChangesAsync()
|
|
44
|
-
Task<bool> ValidateAsync(string input)
|
|
45
|
-
|
|
46
|
-
// ❌ WRONG
|
|
47
|
-
Task<Order> GetOrder(int id)
|
|
48
|
-
Task SaveChanges()
|
|
49
|
-
```
|
|
50
|
-
|
|
51
|
-
---
|
|
52
|
-
|
|
53
|
-
## CancellationToken
|
|
54
|
-
|
|
55
|
-
### Always Accept CancellationToken
|
|
56
|
-
|
|
57
|
-
```csharp
|
|
58
|
-
// ✅ CORRECT
|
|
59
|
-
public async Task<User> GetUserAsync(int id, CancellationToken ct = default)
|
|
60
|
-
{
|
|
61
|
-
return await _context.Users
|
|
62
|
-
.Where(u => u.Id == id)
|
|
63
|
-
.FirstOrDefaultAsync(ct);
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
// ✅ CORRECT (in controller)
|
|
67
|
-
[HttpGet("{id}")]
|
|
68
|
-
public async Task<IActionResult> GetUser(int id, CancellationToken ct)
|
|
69
|
-
{
|
|
70
|
-
var user = await _userService.GetUserAsync(id, ct);
|
|
71
|
-
return Ok(user);
|
|
72
|
-
}
|
|
73
|
-
```
|
|
74
|
-
|
|
75
|
-
### Pass CancellationToken Down
|
|
76
|
-
|
|
77
|
-
```csharp
|
|
78
|
-
public async Task<Order> ProcessOrderAsync(int orderId, CancellationToken ct = default)
|
|
79
|
-
{
|
|
80
|
-
// Pass ct to all async calls
|
|
81
|
-
var order = await _repository.GetByIdAsync(orderId, ct);
|
|
82
|
-
await _paymentService.ChargeAsync(order, ct);
|
|
83
|
-
await _emailService.SendConfirmationAsync(order, ct);
|
|
84
|
-
|
|
85
|
-
return order;
|
|
86
|
-
}
|
|
87
|
-
```
|
|
88
|
-
|
|
89
|
-
---
|
|
90
|
-
|
|
91
|
-
## ConfigureAwait
|
|
92
|
-
|
|
93
|
-
### Library Code
|
|
94
|
-
|
|
95
|
-
Use `ConfigureAwait(false)` in library/infrastructure code:
|
|
96
|
-
|
|
97
|
-
```csharp
|
|
98
|
-
// Infrastructure layer
|
|
99
|
-
public async Task<User> GetByIdAsync(int id)
|
|
100
|
-
{
|
|
101
|
-
return await _context.Users
|
|
102
|
-
.FindAsync(id)
|
|
103
|
-
.ConfigureAwait(false); // ✅ Library code
|
|
104
|
-
}
|
|
105
|
-
```
|
|
106
|
-
|
|
107
|
-
### Application Code
|
|
108
|
-
|
|
109
|
-
DON'T use `ConfigureAwait(false)` in application/API layer:
|
|
110
|
-
|
|
111
|
-
```csharp
|
|
112
|
-
// Controller/Service layer
|
|
113
|
-
public async Task<IActionResult> GetUser(int id)
|
|
114
|
-
{
|
|
115
|
-
// ✅ CORRECT (no ConfigureAwait in app layer)
|
|
116
|
-
var user = await _userService.GetByIdAsync(id);
|
|
117
|
-
return Ok(user);
|
|
118
|
-
}
|
|
119
|
-
```
|
|
120
|
-
|
|
121
|
-
---
|
|
122
|
-
|
|
123
|
-
## Async Best Practices
|
|
124
|
-
|
|
125
|
-
### DO
|
|
126
|
-
|
|
127
|
-
✅ **Use async all the way**
|
|
128
|
-
|
|
129
|
-
```csharp
|
|
130
|
-
// ✅ CORRECT
|
|
131
|
-
public async Task<ActionResult> CreateOrder()
|
|
132
|
-
{
|
|
133
|
-
var order = await _service.CreateOrderAsync();
|
|
134
|
-
await _context.SaveChangesAsync();
|
|
135
|
-
return Ok(order);
|
|
136
|
-
}
|
|
137
|
-
```
|
|
138
|
-
|
|
139
|
-
✅ **Use Task.WhenAll for parallel operations**
|
|
140
|
-
|
|
141
|
-
```csharp
|
|
142
|
-
// ✅ CORRECT (parallel)
|
|
143
|
-
var userTask = _userService.GetUserAsync(userId);
|
|
144
|
-
var ordersTask = _orderService.GetOrdersAsync(userId);
|
|
145
|
-
var settingsTask = _settingsService.GetSettingsAsync(userId);
|
|
146
|
-
|
|
147
|
-
await Task.WhenAll(userTask, ordersTask, settingsTask);
|
|
148
|
-
|
|
149
|
-
var user = await userTask;
|
|
150
|
-
var orders = await ordersTask;
|
|
151
|
-
var settings = await settingsTask;
|
|
152
|
-
```
|
|
153
|
-
|
|
154
|
-
✅ **Return Task directly when no await needed**
|
|
155
|
-
|
|
156
|
-
```csharp
|
|
157
|
-
// ✅ CORRECT (no unnecessary async/await)
|
|
158
|
-
public Task<User> GetUserAsync(int id)
|
|
159
|
-
{
|
|
160
|
-
return _repository.GetByIdAsync(id); // No await needed
|
|
161
|
-
}
|
|
162
|
-
```
|
|
163
|
-
|
|
164
|
-
### DON'T
|
|
165
|
-
|
|
166
|
-
❌ **Don't use async void (except event handlers)**
|
|
167
|
-
|
|
168
|
-
```csharp
|
|
169
|
-
// ❌ WRONG
|
|
170
|
-
public async void ProcessOrder(int id)
|
|
171
|
-
{
|
|
172
|
-
await _service.ProcessAsync(id); // Exceptions swallowed!
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
// ✅ CORRECT
|
|
176
|
-
public async Task ProcessOrderAsync(int id)
|
|
177
|
-
{
|
|
178
|
-
await _service.ProcessAsync(id);
|
|
179
|
-
}
|
|
180
|
-
```
|
|
181
|
-
|
|
182
|
-
❌ **Don't use .Result or .Wait()**
|
|
183
|
-
|
|
184
|
-
```csharp
|
|
185
|
-
// ❌ WRONG (blocks thread, risk of deadlock)
|
|
186
|
-
var user = _userService.GetUserAsync(id).Result;
|
|
187
|
-
_orderService.ProcessAsync(orderId).Wait();
|
|
188
|
-
|
|
189
|
-
// ✅ CORRECT
|
|
190
|
-
var user = await _userService.GetUserAsync(id);
|
|
191
|
-
await _orderService.ProcessAsync(orderId);
|
|
192
|
-
```
|
|
193
|
-
|
|
194
|
-
❌ **Don't create unnecessary tasks**
|
|
195
|
-
|
|
196
|
-
```csharp
|
|
197
|
-
// ❌ WRONG
|
|
198
|
-
public async Task<int> GetCountAsync()
|
|
199
|
-
{
|
|
200
|
-
return await Task.FromResult(_items.Count); // Unnecessary!
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
// ✅ CORRECT
|
|
204
|
-
public Task<int> GetCountAsync()
|
|
205
|
-
{
|
|
206
|
-
return Task.FromResult(_items.Count); // Or just return synchronously
|
|
207
|
-
}
|
|
208
|
-
```
|
|
209
|
-
|
|
210
|
-
---
|
|
211
|
-
|
|
212
|
-
## Async Patterns
|
|
213
|
-
|
|
214
|
-
### Pattern: Retry with Exponential Backoff
|
|
215
|
-
|
|
216
|
-
```csharp
|
|
217
|
-
public async Task<T> RetryAsync<T>(
|
|
218
|
-
Func<Task<T>> operation,
|
|
219
|
-
int maxRetries = 3,
|
|
220
|
-
CancellationToken ct = default)
|
|
221
|
-
{
|
|
222
|
-
for (int i = 0; i < maxRetries; i++)
|
|
223
|
-
{
|
|
224
|
-
try
|
|
225
|
-
{
|
|
226
|
-
return await operation();
|
|
227
|
-
}
|
|
228
|
-
catch (Exception) when (i < maxRetries - 1)
|
|
229
|
-
{
|
|
230
|
-
var delay = TimeSpan.FromSeconds(Math.Pow(2, i)); // 1s, 2s, 4s
|
|
231
|
-
await Task.Delay(delay, ct);
|
|
232
|
-
}
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
throw new InvalidOperationException($"Failed after {maxRetries} retries");
|
|
236
|
-
}
|
|
237
|
-
```
|
|
238
|
-
|
|
239
|
-
### Pattern: Timeout
|
|
240
|
-
|
|
241
|
-
```csharp
|
|
242
|
-
public async Task<User> GetUserWithTimeoutAsync(int id)
|
|
243
|
-
{
|
|
244
|
-
using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(5));
|
|
245
|
-
|
|
246
|
-
try
|
|
247
|
-
{
|
|
248
|
-
return await _repository.GetByIdAsync(id, cts.Token);
|
|
249
|
-
}
|
|
250
|
-
catch (OperationCanceledException)
|
|
251
|
-
{
|
|
252
|
-
throw new TimeoutException("Operation timed out after 5 seconds");
|
|
253
|
-
}
|
|
254
|
-
}
|
|
255
|
-
```
|
|
256
|
-
|
|
257
|
-
### Pattern: Background Work (Fire and Forget)
|
|
258
|
-
|
|
259
|
-
```csharp
|
|
260
|
-
// ❌ WRONG (async void)
|
|
261
|
-
public async void LogAsync(string message)
|
|
262
|
-
{
|
|
263
|
-
await _logger.WriteAsync(message);
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
// ✅ CORRECT (use background service or Hangfire)
|
|
267
|
-
public Task LogAsync(string message)
|
|
268
|
-
{
|
|
269
|
-
_ = Task.Run(async () =>
|
|
270
|
-
{
|
|
271
|
-
try
|
|
272
|
-
{
|
|
273
|
-
await _logger.WriteAsync(message);
|
|
274
|
-
}
|
|
275
|
-
catch (Exception ex)
|
|
276
|
-
{
|
|
277
|
-
// Handle exceptions
|
|
278
|
-
}
|
|
279
|
-
});
|
|
280
|
-
|
|
281
|
-
return Task.CompletedTask;
|
|
282
|
-
}
|
|
283
|
-
```
|
|
284
|
-
|
|
285
|
-
---
|
|
286
|
-
|
|
287
|
-
## Common Mistakes
|
|
288
|
-
|
|
289
|
-
### Mistake 1: Mixing Sync and Async
|
|
290
|
-
|
|
291
|
-
```csharp
|
|
292
|
-
// ❌ WRONG
|
|
293
|
-
public User GetUser(int id)
|
|
294
|
-
{
|
|
295
|
-
return _repository.GetByIdAsync(id).Result; // Deadlock risk!
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
// ✅ CORRECT
|
|
299
|
-
public async Task<User> GetUserAsync(int id)
|
|
300
|
-
{
|
|
301
|
-
return await _repository.GetByIdAsync(id);
|
|
302
|
-
}
|
|
303
|
-
```
|
|
304
|
-
|
|
305
|
-
### Mistake 2: Not Awaiting in Loop
|
|
306
|
-
|
|
307
|
-
```csharp
|
|
308
|
-
// ❌ WRONG (sequential, slow)
|
|
309
|
-
foreach (var id in userIds)
|
|
310
|
-
{
|
|
311
|
-
await _service.ProcessAsync(id);
|
|
312
|
-
}
|
|
313
|
-
|
|
314
|
-
// ✅ CORRECT (parallel)
|
|
315
|
-
var tasks = userIds.Select(id => _service.ProcessAsync(id));
|
|
316
|
-
await Task.WhenAll(tasks);
|
|
317
|
-
```
|
|
318
|
-
|
|
319
|
-
### Mistake 3: Unnecessary Async/Await
|
|
320
|
-
|
|
321
|
-
```csharp
|
|
322
|
-
// ❌ WRONG (extra state machine)
|
|
323
|
-
public async Task<User> GetUserAsync(int id)
|
|
324
|
-
{
|
|
325
|
-
return await _repository.GetByIdAsync(id);
|
|
326
|
-
}
|
|
327
|
-
|
|
328
|
-
// ✅ CORRECT (no async needed)
|
|
329
|
-
public Task<User> GetUserAsync(int id)
|
|
330
|
-
{
|
|
331
|
-
return _repository.GetByIdAsync(id);
|
|
332
|
-
}
|
|
333
|
-
```
|
|
334
|
-
|
|
335
|
-
---
|
|
336
|
-
|
|
337
|
-
## Blazor-Specific
|
|
338
|
-
|
|
339
|
-
### Async in OnInitializedAsync
|
|
340
|
-
|
|
341
|
-
```csharp
|
|
342
|
-
// ✅ CORRECT
|
|
343
|
-
protected override async Task OnInitializedAsync()
|
|
344
|
-
{
|
|
345
|
-
users = await UserService.GetUsersAsync();
|
|
346
|
-
StateHasChanged(); // Optional, called automatically
|
|
347
|
-
}
|
|
348
|
-
```
|
|
349
|
-
|
|
350
|
-
### Async Event Handlers
|
|
351
|
-
|
|
352
|
-
```csharp
|
|
353
|
-
// ✅ CORRECT
|
|
354
|
-
private async Task HandleSubmitAsync()
|
|
355
|
-
{
|
|
356
|
-
await OrderService.CreateAsync(order);
|
|
357
|
-
NavigationManager.NavigateTo("/orders");
|
|
358
|
-
}
|
|
359
|
-
|
|
360
|
-
// In Razor:
|
|
361
|
-
<button @onclick="HandleSubmitAsync">Submit</button>
|
|
362
|
-
```
|
|
363
|
-
|
|
364
|
-
---
|
|
365
|
-
|
|
366
|
-
*MORPH-SPEC by Polymorphism Tech*
|
|
@@ -1,117 +0,0 @@
|
|
|
1
|
-
# .NET 10 Package Compatibility Matrix
|
|
2
|
-
|
|
3
|
-
> **Scope:** universal
|
|
4
|
-
> **Layer:** 0 (always load)
|
|
5
|
-
> **Keywords:** dotnet, net10, csharp, patterns, core
|
|
6
|
-
> **Load When:** always
|
|
7
|
-
|
|
8
|
-
## Package Matrix
|
|
9
|
-
|
|
10
|
-
| Package | .NET 9 (Last) | .NET 10 (Min) | Breaking Changes |
|
|
11
|
-
|---------|---------------|---------------|------------------|
|
|
12
|
-
| **MudBlazor** | 6.21.0 | **>= 8.15.0** | Theme API, generics, events |
|
|
13
|
-
| **FluentUI.Blazor** | 4.x | **>= 5.0.0** | Component params, icon system |
|
|
14
|
-
| **Hangfire.AspNetCore** | 1.8.x | **>= 1.8.22** | None (TFM update only) |
|
|
15
|
-
| **EF Core** | 9.x | **10.0.0** | Vector search, primitive collections |
|
|
16
|
-
| **Azure.Storage.Blobs** | 12.19.x | **>= 12.20.0** | None |
|
|
17
|
-
| **Agent Framework** | N/A | **>= 1.0.0** | Replaces Semantic Kernel |
|
|
18
|
-
|
|
19
|
-
---
|
|
20
|
-
|
|
21
|
-
## MudBlazor 6.x → 8.x
|
|
22
|
-
|
|
23
|
-
```csharp
|
|
24
|
-
// Theme API
|
|
25
|
-
// WRONG (v6): new MudTheme { Palette = new Palette { Primary = "#7C3AED" } }
|
|
26
|
-
// CORRECT (v8):
|
|
27
|
-
var theme = new MudTheme
|
|
28
|
-
{
|
|
29
|
-
PaletteLight = new PaletteLight { Primary = "#7C3AED" },
|
|
30
|
-
PaletteDark = new PaletteDark { Primary = "#9D74F2" }
|
|
31
|
-
};
|
|
32
|
-
|
|
33
|
-
// Generic components
|
|
34
|
-
// WRONG (v6): <MudChip OnClose="HandleClose">
|
|
35
|
-
// CORRECT (v8): <MudChip T="string" Closed="HandleClosed">Tag</MudChip>
|
|
36
|
-
|
|
37
|
-
// Dialog
|
|
38
|
-
// WRONG (v6): <MudDialog DisableBackdropClick="true">
|
|
39
|
-
// CORRECT (v8): <MudDialog BackdropClick="() => {}">
|
|
40
|
-
```
|
|
41
|
-
|
|
42
|
-
**Migration:** `Palette` → `PaletteLight`/`PaletteDark`, `OnClose` → `Closed`, `DisableBackdropClick` → `BackdropClick`
|
|
43
|
-
|
|
44
|
-
---
|
|
45
|
-
|
|
46
|
-
## Fluent UI 4.x → 5.x
|
|
47
|
-
|
|
48
|
-
```csharp
|
|
49
|
-
// Component params: Appearance now requires @
|
|
50
|
-
// WRONG (v4): <FluentButton Appearance="Appearance.Accent">
|
|
51
|
-
// CORRECT (v5): <FluentButton Appearance="@Appearance.Accent">
|
|
52
|
-
|
|
53
|
-
// Icon system
|
|
54
|
-
// WRONG (v4): <FluentIcon Name="@FluentIcons.Add" />
|
|
55
|
-
// CORRECT (v5): <FluentIcon Icon="@Icons.Add" />
|
|
56
|
-
```
|
|
57
|
-
|
|
58
|
-
> **Ref:** `fluent-ui-blazor.md` for full Fluent UI API reference.
|
|
59
|
-
|
|
60
|
-
---
|
|
61
|
-
|
|
62
|
-
## EF Core 10 New Features
|
|
63
|
-
|
|
64
|
-
```csharp
|
|
65
|
-
// Vector search (Azure SQL)
|
|
66
|
-
[Column(TypeName = "vector(384)")]
|
|
67
|
-
public float[] Embedding { get; set; } = Array.Empty<float>();
|
|
68
|
-
|
|
69
|
-
var similar = await context.Products
|
|
70
|
-
.OrderBy(p => EF.Functions.VectorDistance(p.Embedding, searchEmbedding))
|
|
71
|
-
.Take(10).ToListAsync();
|
|
72
|
-
|
|
73
|
-
// Primitive collections (stored as JSON)
|
|
74
|
-
public List<string> Roles { get; set; } = new();
|
|
75
|
-
```
|
|
76
|
-
|
|
77
|
-
**Breaking:** Required navigation properties now throw if not loaded. Query splitting behavior changed.
|
|
78
|
-
|
|
79
|
-
---
|
|
80
|
-
|
|
81
|
-
## Agent Framework (replaces Semantic Kernel)
|
|
82
|
-
|
|
83
|
-
```csharp
|
|
84
|
-
// DEPRECATED (Semantic Kernel)
|
|
85
|
-
var kernel = Kernel.CreateBuilder().AddAzureOpenAIChatCompletion(...).Build();
|
|
86
|
-
|
|
87
|
-
// NEW (Microsoft Agent Framework)
|
|
88
|
-
var agent = new Agent().WithModel("gpt-4").WithInstructions("...");
|
|
89
|
-
var response = await agent.RunAsync("Summarize this text...");
|
|
90
|
-
```
|
|
91
|
-
|
|
92
|
-
> **Ref:** `stacks/blazor-azure/.morph/standards/agent-framework-setup.md` for full migration guide.
|
|
93
|
-
|
|
94
|
-
---
|
|
95
|
-
|
|
96
|
-
## Troubleshooting
|
|
97
|
-
|
|
98
|
-
| Issue | Cause | Fix |
|
|
99
|
-
|-------|-------|-----|
|
|
100
|
-
| "JS interop not initialized" | Incompatible UI lib version | Upgrade to .NET 10 compatible version |
|
|
101
|
-
| "Cannot find PaletteLight" | MudBlazor 6.x API with 8.x | Use `PaletteLight`/`PaletteDark` |
|
|
102
|
-
| CS0618 deprecation warnings | Old API still compiles | Migrate to new API |
|
|
103
|
-
|
|
104
|
-
## Migration Checklist
|
|
105
|
-
|
|
106
|
-
- [ ] Git commit/branch (backup)
|
|
107
|
-
- [ ] `TargetFramework` → `net10.0`
|
|
108
|
-
- [ ] Update all `Microsoft.*` to 10.x
|
|
109
|
-
- [ ] EF Core → 10.0.x
|
|
110
|
-
- [ ] MudBlazor → 8.15.0+ (if used): theme, generics, events
|
|
111
|
-
- [ ] Fluent UI → 5.0.0+ (if used): params, icons
|
|
112
|
-
- [ ] Build succeeds + all tests pass
|
|
113
|
-
- [ ] UI renders correctly
|
|
114
|
-
|
|
115
|
-
---
|
|
116
|
-
|
|
117
|
-
*MORPH-SPEC by Polymorphism Tech*
|