antigravity-devkit 1.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/LICENSE +21 -0
- package/README.md +421 -0
- package/bin/cli.js +179 -0
- package/package.json +38 -0
- package/template/ARCHITECTURE.md +148 -0
- package/template/README.md +421 -0
- package/template/agents/backend-specialist.md +137 -0
- package/template/agents/database-architect.md +114 -0
- package/template/agents/debugger.md +108 -0
- package/template/agents/devops-engineer.md +125 -0
- package/template/agents/documentation-writer.md +109 -0
- package/template/agents/explorer-agent.md +107 -0
- package/template/agents/frontend-specialist.md +231 -0
- package/template/agents/orchestrator.md +100 -0
- package/template/agents/performance-optimizer.md +109 -0
- package/template/agents/project-planner.md +123 -0
- package/template/agents/security-auditor.md +107 -0
- package/template/agents/test-engineer.md +133 -0
- package/template/rules/GEMINI.md +180 -0
- package/template/scripts/checklist.py +170 -0
- package/template/scripts/verify_all.py +243 -0
- package/template/skills/api-patterns/SKILL.md +116 -0
- package/template/skills/architecture/SKILL.md +98 -0
- package/template/skills/aspnet-patterns/SKILL.md +120 -0
- package/template/skills/azure-aks/SKILL.md +136 -0
- package/template/skills/azure-devops/SKILL.md +123 -0
- package/template/skills/azure-keyvault/SKILL.md +100 -0
- package/template/skills/brainstorming/SKILL.md +96 -0
- package/template/skills/clean-code/SKILL.md +84 -0
- package/template/skills/csharp-patterns/SKILL.md +115 -0
- package/template/skills/documentation-templates/SKILL.md +127 -0
- package/template/skills/english-education/SKILL.md +116 -0
- package/template/skills/english-education/references/lesson-templates.md +151 -0
- package/template/skills/english-education/references/quiz-templates.md +177 -0
- package/template/skills/english-education/scripts/curriculum_validator.py +175 -0
- package/template/skills/frontend-design/SKILL.md +199 -0
- package/template/skills/frontend-design/animation-guide.md +217 -0
- package/template/skills/frontend-design/design-systems.md +230 -0
- package/template/skills/frontend-design/ux-psychology.md +128 -0
- package/template/skills/gitops-patterns/SKILL.md +105 -0
- package/template/skills/grafana-logging/SKILL.md +107 -0
- package/template/skills/intelligent-routing/SKILL.md +75 -0
- package/template/skills/plan-writing/SKILL.md +96 -0
- package/template/skills/sqlserver-design/SKILL.md +97 -0
- package/template/skills/systematic-debugging/SKILL.md +98 -0
- package/template/skills/testing-patterns/SKILL.md +102 -0
- package/template/skills/vitest-testing/SKILL.md +116 -0
- package/template/skills/vue3-patterns/SKILL.md +195 -0
- package/template/skills/vulnerability-scanner/SKILL.md +104 -0
- package/template/skills/xunit-testing/SKILL.md +127 -0
- package/template/workflows/brainstorm.md +69 -0
- package/template/workflows/code.md +82 -0
- package/template/workflows/create.md +79 -0
- package/template/workflows/debug.md +83 -0
- package/template/workflows/deploy.md +101 -0
- package/template/workflows/orchestrate.md +86 -0
- package/template/workflows/plan.md +79 -0
- package/template/workflows/review.md +85 -0
- package/template/workflows/status.md +90 -0
- package/template/workflows/test.md +89 -0
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Verify All - Comprehensive project verification
|
|
4
|
+
Run before deployment or releases.
|
|
5
|
+
|
|
6
|
+
Usage:
|
|
7
|
+
python .agent-antigravity/scripts/verify_all.py .
|
|
8
|
+
python .agent-antigravity/scripts/verify_all.py . --url http://localhost:3000
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
import subprocess
|
|
12
|
+
import sys
|
|
13
|
+
import os
|
|
14
|
+
from pathlib import Path
|
|
15
|
+
from datetime import datetime
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def run_command(cmd: list[str], cwd: str = ".") -> tuple[int, str]:
|
|
19
|
+
"""Run a command and return exit code and output."""
|
|
20
|
+
try:
|
|
21
|
+
result = subprocess.run(
|
|
22
|
+
cmd,
|
|
23
|
+
cwd=cwd,
|
|
24
|
+
capture_output=True,
|
|
25
|
+
text=True,
|
|
26
|
+
timeout=600
|
|
27
|
+
)
|
|
28
|
+
return result.returncode, result.stdout + result.stderr
|
|
29
|
+
except subprocess.TimeoutExpired:
|
|
30
|
+
return 1, "Command timed out"
|
|
31
|
+
except FileNotFoundError:
|
|
32
|
+
return 1, f"Command not found: {cmd[0]}"
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
class Verifier:
|
|
36
|
+
def __init__(self, project_path: str, url: str = None):
|
|
37
|
+
self.project_path = project_path
|
|
38
|
+
self.url = url
|
|
39
|
+
self.results = []
|
|
40
|
+
|
|
41
|
+
def add_result(self, category: str, name: str, passed: bool, details: str = ""):
|
|
42
|
+
self.results.append({
|
|
43
|
+
"category": category,
|
|
44
|
+
"name": name,
|
|
45
|
+
"passed": passed,
|
|
46
|
+
"details": details
|
|
47
|
+
})
|
|
48
|
+
|
|
49
|
+
def run_all(self):
|
|
50
|
+
"""Run all verification checks."""
|
|
51
|
+
print("=" * 70)
|
|
52
|
+
print("COMPREHENSIVE PROJECT VERIFICATION")
|
|
53
|
+
print(f"Started: {datetime.now().isoformat()}")
|
|
54
|
+
print("=" * 70)
|
|
55
|
+
|
|
56
|
+
self.verify_security()
|
|
57
|
+
self.verify_code_quality()
|
|
58
|
+
self.verify_tests()
|
|
59
|
+
self.verify_build()
|
|
60
|
+
self.verify_dependencies()
|
|
61
|
+
|
|
62
|
+
if self.url:
|
|
63
|
+
self.verify_runtime(self.url)
|
|
64
|
+
|
|
65
|
+
self.print_summary()
|
|
66
|
+
|
|
67
|
+
def verify_security(self):
|
|
68
|
+
"""Security verification."""
|
|
69
|
+
print("\n[SECURITY]")
|
|
70
|
+
|
|
71
|
+
# Check for secrets
|
|
72
|
+
secret_patterns = [
|
|
73
|
+
("password", "password="),
|
|
74
|
+
("api_key", "apikey="),
|
|
75
|
+
("secret", "secret="),
|
|
76
|
+
("connection_string", "connectionstring="),
|
|
77
|
+
]
|
|
78
|
+
|
|
79
|
+
for name, pattern in secret_patterns:
|
|
80
|
+
code, output = run_command(
|
|
81
|
+
["grep", "-ri", pattern, "--include=*.cs", "--include=*.ts"],
|
|
82
|
+
self.project_path
|
|
83
|
+
)
|
|
84
|
+
passed = code != 0 or not output.strip()
|
|
85
|
+
self.add_result("Security", f"No hardcoded {name}", passed)
|
|
86
|
+
print(f" {'✅' if passed else '❌'} No hardcoded {name}")
|
|
87
|
+
|
|
88
|
+
# npm audit
|
|
89
|
+
package_json = Path(self.project_path) / "package.json"
|
|
90
|
+
if package_json.exists():
|
|
91
|
+
code, output = run_command(["npm", "audit", "--audit-level=critical"], self.project_path)
|
|
92
|
+
passed = code == 0
|
|
93
|
+
self.add_result("Security", "npm audit (critical)", passed, output[:200])
|
|
94
|
+
print(f" {'✅' if passed else '❌'} npm audit (critical)")
|
|
95
|
+
|
|
96
|
+
def verify_code_quality(self):
|
|
97
|
+
"""Code quality verification."""
|
|
98
|
+
print("\n[CODE QUALITY]")
|
|
99
|
+
|
|
100
|
+
# Frontend lint
|
|
101
|
+
package_json = Path(self.project_path) / "package.json"
|
|
102
|
+
if package_json.exists():
|
|
103
|
+
code, output = run_command(["npm", "run", "lint"], self.project_path)
|
|
104
|
+
passed = code == 0
|
|
105
|
+
self.add_result("Code Quality", "Frontend lint", passed)
|
|
106
|
+
print(f" {'✅' if passed else '❌'} Frontend lint")
|
|
107
|
+
|
|
108
|
+
# TypeScript
|
|
109
|
+
code, output = run_command(["npx", "tsc", "--noEmit"], self.project_path)
|
|
110
|
+
passed = code == 0
|
|
111
|
+
self.add_result("Code Quality", "TypeScript check", passed)
|
|
112
|
+
print(f" {'✅' if passed else '❌'} TypeScript check")
|
|
113
|
+
|
|
114
|
+
# Backend lint (if applicable)
|
|
115
|
+
csproj_files = list(Path(self.project_path).glob("**/*.csproj"))
|
|
116
|
+
if csproj_files:
|
|
117
|
+
code, output = run_command(["dotnet", "format", "--verify-no-changes"], self.project_path)
|
|
118
|
+
passed = code == 0
|
|
119
|
+
self.add_result("Code Quality", "C# formatting", passed)
|
|
120
|
+
print(f" {'✅' if passed else '❌'} C# formatting")
|
|
121
|
+
|
|
122
|
+
def verify_tests(self):
|
|
123
|
+
"""Test verification."""
|
|
124
|
+
print("\n[TESTS]")
|
|
125
|
+
|
|
126
|
+
# Frontend tests
|
|
127
|
+
package_json = Path(self.project_path) / "package.json"
|
|
128
|
+
if package_json.exists():
|
|
129
|
+
code, output = run_command(["npm", "run", "test", "--", "--run"], self.project_path)
|
|
130
|
+
passed = code == 0
|
|
131
|
+
self.add_result("Tests", "Frontend tests", passed)
|
|
132
|
+
print(f" {'✅' if passed else '❌'} Frontend tests")
|
|
133
|
+
|
|
134
|
+
# Backend tests
|
|
135
|
+
sln_files = list(Path(self.project_path).glob("*.sln"))
|
|
136
|
+
if sln_files:
|
|
137
|
+
code, output = run_command(["dotnet", "test"], self.project_path)
|
|
138
|
+
passed = code == 0
|
|
139
|
+
self.add_result("Tests", "Backend tests", passed)
|
|
140
|
+
print(f" {'✅' if passed else '❌'} Backend tests")
|
|
141
|
+
|
|
142
|
+
def verify_build(self):
|
|
143
|
+
"""Build verification."""
|
|
144
|
+
print("\n[BUILD]")
|
|
145
|
+
|
|
146
|
+
# Frontend build
|
|
147
|
+
package_json = Path(self.project_path) / "package.json"
|
|
148
|
+
if package_json.exists():
|
|
149
|
+
code, output = run_command(["npm", "run", "build"], self.project_path)
|
|
150
|
+
passed = code == 0
|
|
151
|
+
self.add_result("Build", "Frontend build", passed)
|
|
152
|
+
print(f" {'✅' if passed else '❌'} Frontend build")
|
|
153
|
+
|
|
154
|
+
# Backend build
|
|
155
|
+
sln_files = list(Path(self.project_path).glob("*.sln"))
|
|
156
|
+
if sln_files:
|
|
157
|
+
code, output = run_command(["dotnet", "build", "-c", "Release"], self.project_path)
|
|
158
|
+
passed = code == 0
|
|
159
|
+
self.add_result("Build", "Backend build", passed)
|
|
160
|
+
print(f" {'✅' if passed else '❌'} Backend build")
|
|
161
|
+
|
|
162
|
+
def verify_dependencies(self):
|
|
163
|
+
"""Dependency verification."""
|
|
164
|
+
print("\n[DEPENDENCIES]")
|
|
165
|
+
|
|
166
|
+
# npm outdated
|
|
167
|
+
package_json = Path(self.project_path) / "package.json"
|
|
168
|
+
if package_json.exists():
|
|
169
|
+
code, output = run_command(["npm", "outdated"], self.project_path)
|
|
170
|
+
# outdated returns 1 if there are outdated packages
|
|
171
|
+
self.add_result("Dependencies", "npm packages", True, "Check npm outdated for details")
|
|
172
|
+
print(f" ℹ️ npm outdated check complete")
|
|
173
|
+
|
|
174
|
+
# dotnet outdated (if tool installed)
|
|
175
|
+
sln_files = list(Path(self.project_path).glob("*.sln"))
|
|
176
|
+
if sln_files:
|
|
177
|
+
code, output = run_command(["dotnet", "list", "package", "--outdated"], self.project_path)
|
|
178
|
+
self.add_result("Dependencies", "NuGet packages", True, "Check dotnet list package for details")
|
|
179
|
+
print(f" ℹ️ NuGet outdated check complete")
|
|
180
|
+
|
|
181
|
+
def verify_runtime(self, url: str):
|
|
182
|
+
"""Runtime verification (if URL provided)."""
|
|
183
|
+
print("\n[RUNTIME]")
|
|
184
|
+
|
|
185
|
+
# Health check
|
|
186
|
+
code, output = run_command(["curl", "-s", "-o", "/dev/null", "-w", "%{http_code}", f"{url}/health"])
|
|
187
|
+
passed = output.strip() == "200"
|
|
188
|
+
self.add_result("Runtime", "Health check", passed)
|
|
189
|
+
print(f" {'✅' if passed else '❌'} Health check")
|
|
190
|
+
|
|
191
|
+
def print_summary(self):
|
|
192
|
+
"""Print verification summary."""
|
|
193
|
+
print("\n" + "=" * 70)
|
|
194
|
+
print("VERIFICATION SUMMARY")
|
|
195
|
+
print("=" * 70)
|
|
196
|
+
|
|
197
|
+
categories = {}
|
|
198
|
+
for r in self.results:
|
|
199
|
+
cat = r["category"]
|
|
200
|
+
if cat not in categories:
|
|
201
|
+
categories[cat] = []
|
|
202
|
+
categories[cat].append(r)
|
|
203
|
+
|
|
204
|
+
total_passed = 0
|
|
205
|
+
total_count = 0
|
|
206
|
+
|
|
207
|
+
for cat, items in categories.items():
|
|
208
|
+
print(f"\n{cat}:")
|
|
209
|
+
for item in items:
|
|
210
|
+
status = "✅" if item["passed"] else "❌"
|
|
211
|
+
print(f" {status} {item['name']}")
|
|
212
|
+
total_count += 1
|
|
213
|
+
if item["passed"]:
|
|
214
|
+
total_passed += 1
|
|
215
|
+
|
|
216
|
+
print("\n" + "-" * 70)
|
|
217
|
+
print(f"Total: {total_passed}/{total_count} checks passed")
|
|
218
|
+
|
|
219
|
+
if total_passed < total_count:
|
|
220
|
+
print("\n❌ Some checks failed. Review and fix before deployment.")
|
|
221
|
+
sys.exit(1)
|
|
222
|
+
else:
|
|
223
|
+
print("\n✅ All checks passed! Ready for deployment.")
|
|
224
|
+
|
|
225
|
+
|
|
226
|
+
def main():
|
|
227
|
+
if len(sys.argv) < 2:
|
|
228
|
+
print("Usage: python verify_all.py <project_path> [--url <url>]")
|
|
229
|
+
sys.exit(1)
|
|
230
|
+
|
|
231
|
+
project_path = sys.argv[1]
|
|
232
|
+
url = None
|
|
233
|
+
if "--url" in sys.argv:
|
|
234
|
+
url_index = sys.argv.index("--url") + 1
|
|
235
|
+
if url_index < len(sys.argv):
|
|
236
|
+
url = sys.argv[url_index]
|
|
237
|
+
|
|
238
|
+
verifier = Verifier(project_path, url)
|
|
239
|
+
verifier.run_all()
|
|
240
|
+
|
|
241
|
+
|
|
242
|
+
if __name__ == "__main__":
|
|
243
|
+
main()
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: api-patterns
|
|
3
|
+
description: REST API design patterns and best practices
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# API Patterns
|
|
7
|
+
|
|
8
|
+
> RESTful API design for ASP.NET Core.
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
## REST Conventions
|
|
13
|
+
|
|
14
|
+
| Method | Action | Route | Response |
|
|
15
|
+
|--------|--------|-------|----------|
|
|
16
|
+
| GET | List | /api/users | 200 + array |
|
|
17
|
+
| GET | Read | /api/users/{id} | 200 or 404 |
|
|
18
|
+
| POST | Create | /api/users | 201 + object |
|
|
19
|
+
| PUT | Update | /api/users/{id} | 200 or 404 |
|
|
20
|
+
| DELETE | Delete | /api/users/{id} | 204 or 404 |
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
## Response Format
|
|
25
|
+
|
|
26
|
+
```csharp
|
|
27
|
+
public class ApiResponse<T>
|
|
28
|
+
{
|
|
29
|
+
public bool Success { get; set; }
|
|
30
|
+
public T? Data { get; set; }
|
|
31
|
+
public string? Error { get; set; }
|
|
32
|
+
public List<string>? Errors { get; set; }
|
|
33
|
+
}
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
## Pagination
|
|
39
|
+
|
|
40
|
+
```csharp
|
|
41
|
+
[HttpGet]
|
|
42
|
+
public async Task<ActionResult<PagedResult<UserDto>>> GetUsers(
|
|
43
|
+
[FromQuery] int page = 1,
|
|
44
|
+
[FromQuery] int pageSize = 20)
|
|
45
|
+
{
|
|
46
|
+
var result = await _service.GetPagedAsync(page, pageSize);
|
|
47
|
+
return Ok(result);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
public class PagedResult<T>
|
|
51
|
+
{
|
|
52
|
+
public List<T> Items { get; set; }
|
|
53
|
+
public int TotalCount { get; set; }
|
|
54
|
+
public int Page { get; set; }
|
|
55
|
+
public int PageSize { get; set; }
|
|
56
|
+
}
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
---
|
|
60
|
+
|
|
61
|
+
## Validation
|
|
62
|
+
|
|
63
|
+
```csharp
|
|
64
|
+
public class CreateUserDto
|
|
65
|
+
{
|
|
66
|
+
[Required]
|
|
67
|
+
[EmailAddress]
|
|
68
|
+
public string Email { get; set; }
|
|
69
|
+
|
|
70
|
+
[Required]
|
|
71
|
+
[StringLength(100, MinimumLength = 2)]
|
|
72
|
+
public string Name { get; set; }
|
|
73
|
+
}
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
---
|
|
77
|
+
|
|
78
|
+
## Error Handling
|
|
79
|
+
|
|
80
|
+
```csharp
|
|
81
|
+
// Global exception handler
|
|
82
|
+
app.UseExceptionHandler(app =>
|
|
83
|
+
{
|
|
84
|
+
app.Run(async context =>
|
|
85
|
+
{
|
|
86
|
+
context.Response.StatusCode = 500;
|
|
87
|
+
await context.Response.WriteAsJsonAsync(new ApiResponse<object>
|
|
88
|
+
{
|
|
89
|
+
Success = false,
|
|
90
|
+
Error = "An error occurred"
|
|
91
|
+
});
|
|
92
|
+
});
|
|
93
|
+
});
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
---
|
|
97
|
+
|
|
98
|
+
## Versioning
|
|
99
|
+
|
|
100
|
+
```csharp
|
|
101
|
+
[ApiController]
|
|
102
|
+
[Route("api/v{version:apiVersion}/[controller]")]
|
|
103
|
+
[ApiVersion("1.0")]
|
|
104
|
+
public class UsersController : ControllerBase
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
---
|
|
108
|
+
|
|
109
|
+
## DO / DON'T
|
|
110
|
+
|
|
111
|
+
| ✅ Do | ❌ Don't |
|
|
112
|
+
|-------|---------|
|
|
113
|
+
| Consistent responses | Mixed formats |
|
|
114
|
+
| Proper status codes | 200 for everything |
|
|
115
|
+
| Validate input | Trust user data |
|
|
116
|
+
| Version APIs | Breaking changes |
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: architecture
|
|
3
|
+
description: System design patterns and architecture decisions
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Architecture Patterns
|
|
7
|
+
|
|
8
|
+
> System design for Vue3 + ASP.NET applications.
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
## Layered Architecture
|
|
13
|
+
|
|
14
|
+
```
|
|
15
|
+
┌─────────────────────────────────────┐
|
|
16
|
+
│ Presentation (Vue3) │
|
|
17
|
+
├─────────────────────────────────────┤
|
|
18
|
+
│ API (Controllers) │
|
|
19
|
+
├─────────────────────────────────────┤
|
|
20
|
+
│ Business Logic (Services) │
|
|
21
|
+
├─────────────────────────────────────┤
|
|
22
|
+
│ Data Access (Repositories) │
|
|
23
|
+
├─────────────────────────────────────┤
|
|
24
|
+
│ Database (SQL Server) │
|
|
25
|
+
└─────────────────────────────────────┘
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
## Frontend Architecture
|
|
31
|
+
|
|
32
|
+
```
|
|
33
|
+
src/
|
|
34
|
+
├── components/ # Reusable UI components
|
|
35
|
+
├── composables/ # Shared logic (useXxx)
|
|
36
|
+
├── views/ # Page components
|
|
37
|
+
├── stores/ # Pinia stores
|
|
38
|
+
├── api/ # API client
|
|
39
|
+
├── types/ # TypeScript types
|
|
40
|
+
└── router/ # Vue Router
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
---
|
|
44
|
+
|
|
45
|
+
## Backend Architecture
|
|
46
|
+
|
|
47
|
+
```
|
|
48
|
+
src/
|
|
49
|
+
├── Controllers/ # HTTP endpoints
|
|
50
|
+
├── Services/ # Business logic
|
|
51
|
+
├── Repositories/ # Data access
|
|
52
|
+
├── Models/ # Domain models
|
|
53
|
+
├── DTOs/ # Data transfer objects
|
|
54
|
+
└── Infrastructure/ # Cross-cutting concerns
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
---
|
|
58
|
+
|
|
59
|
+
## Communication Patterns
|
|
60
|
+
|
|
61
|
+
| Pattern | Use Case |
|
|
62
|
+
|---------|----------|
|
|
63
|
+
| REST API | Standard CRUD operations |
|
|
64
|
+
| SignalR | Real-time updates |
|
|
65
|
+
| Background Jobs | Async processing |
|
|
66
|
+
| Message Queue | Event-driven systems |
|
|
67
|
+
|
|
68
|
+
---
|
|
69
|
+
|
|
70
|
+
## Decision Matrix
|
|
71
|
+
|
|
72
|
+
| Decision | Option A | Option B |
|
|
73
|
+
|----------|----------|----------|
|
|
74
|
+
| State management | Pinia | Composables |
|
|
75
|
+
| API calls | Axios | Fetch |
|
|
76
|
+
| Forms | VeeValidate | Native |
|
|
77
|
+
| Testing | Vitest | Jest |
|
|
78
|
+
|
|
79
|
+
---
|
|
80
|
+
|
|
81
|
+
## Scaling Considerations
|
|
82
|
+
|
|
83
|
+
| Layer | Strategy |
|
|
84
|
+
|-------|----------|
|
|
85
|
+
| Frontend | CDN, code splitting |
|
|
86
|
+
| API | Horizontal scaling, load balancer |
|
|
87
|
+
| Database | Read replicas, caching |
|
|
88
|
+
| Background | Worker processes |
|
|
89
|
+
|
|
90
|
+
---
|
|
91
|
+
|
|
92
|
+
## DO / DON'T
|
|
93
|
+
|
|
94
|
+
| ✅ Do | ❌ Don't |
|
|
95
|
+
|-------|---------|
|
|
96
|
+
| Clear layer separation | Mixed concerns |
|
|
97
|
+
| Dependency injection | Hard dependencies |
|
|
98
|
+
| Interface-based design | Concrete dependencies |
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: aspnet-patterns
|
|
3
|
+
description: ASP.NET Core patterns - Controllers, Services, Middleware
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# ASP.NET Core Patterns
|
|
7
|
+
|
|
8
|
+
> Clean architecture for ASP.NET Core applications.
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
## Architecture
|
|
13
|
+
|
|
14
|
+
```
|
|
15
|
+
Controller → Service → Repository → Database
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
| Layer | Responsibility |
|
|
19
|
+
|-------|----------------|
|
|
20
|
+
| Controller | HTTP handling, validation |
|
|
21
|
+
| Service | Business logic |
|
|
22
|
+
| Repository | Data access |
|
|
23
|
+
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
## Controller Pattern
|
|
27
|
+
|
|
28
|
+
```csharp
|
|
29
|
+
[ApiController]
|
|
30
|
+
[Route("api/[controller]")]
|
|
31
|
+
public class UsersController : ControllerBase
|
|
32
|
+
{
|
|
33
|
+
private readonly IUserService _userService;
|
|
34
|
+
|
|
35
|
+
public UsersController(IUserService userService)
|
|
36
|
+
{
|
|
37
|
+
_userService = userService;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
[HttpGet("{id}")]
|
|
41
|
+
public async Task<ActionResult<UserDto>> GetById(int id)
|
|
42
|
+
{
|
|
43
|
+
var user = await _userService.GetByIdAsync(id);
|
|
44
|
+
return user is null ? NotFound() : Ok(user);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
[HttpPost]
|
|
48
|
+
public async Task<ActionResult<UserDto>> Create(CreateUserDto dto)
|
|
49
|
+
{
|
|
50
|
+
var user = await _userService.CreateAsync(dto);
|
|
51
|
+
return CreatedAtAction(nameof(GetById), new { id = user.Id }, user);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
---
|
|
57
|
+
|
|
58
|
+
## Service Pattern
|
|
59
|
+
|
|
60
|
+
```csharp
|
|
61
|
+
public class UserService : IUserService
|
|
62
|
+
{
|
|
63
|
+
private readonly IUserRepository _repository;
|
|
64
|
+
|
|
65
|
+
public UserService(IUserRepository repository)
|
|
66
|
+
{
|
|
67
|
+
_repository = repository;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
public async Task<UserDto?> GetByIdAsync(int id)
|
|
71
|
+
{
|
|
72
|
+
var user = await _repository.GetByIdAsync(id);
|
|
73
|
+
return user?.ToDto();
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
---
|
|
79
|
+
|
|
80
|
+
## Dependency Injection
|
|
81
|
+
|
|
82
|
+
```csharp
|
|
83
|
+
// Program.cs
|
|
84
|
+
builder.Services.AddScoped<IUserService, UserService>();
|
|
85
|
+
builder.Services.AddScoped<IUserRepository, UserRepository>();
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
---
|
|
89
|
+
|
|
90
|
+
## Response Format
|
|
91
|
+
|
|
92
|
+
```csharp
|
|
93
|
+
public class ApiResponse<T>
|
|
94
|
+
{
|
|
95
|
+
public bool Success { get; set; }
|
|
96
|
+
public T? Data { get; set; }
|
|
97
|
+
public string? Error { get; set; }
|
|
98
|
+
}
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
---
|
|
102
|
+
|
|
103
|
+
## HTTP Status Codes
|
|
104
|
+
|
|
105
|
+
| Method | Success | Error |
|
|
106
|
+
|--------|---------|-------|
|
|
107
|
+
| GET | 200 OK | 404 Not Found |
|
|
108
|
+
| POST | 201 Created | 400 Bad Request |
|
|
109
|
+
| PUT | 200 OK | 404 Not Found |
|
|
110
|
+
| DELETE | 204 No Content | 404 Not Found |
|
|
111
|
+
|
|
112
|
+
---
|
|
113
|
+
|
|
114
|
+
## DO / DON'T
|
|
115
|
+
|
|
116
|
+
| ✅ Do | ❌ Don't |
|
|
117
|
+
|-------|---------|
|
|
118
|
+
| Async/await | Blocking calls |
|
|
119
|
+
| DI everywhere | `new` in controllers |
|
|
120
|
+
| Proper status codes | 200 for everything |
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: azure-aks
|
|
3
|
+
description: Azure Kubernetes Service deployment patterns
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Azure AKS
|
|
7
|
+
|
|
8
|
+
> Kubernetes deployment for Azure.
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
## Deployment Manifest
|
|
13
|
+
|
|
14
|
+
```yaml
|
|
15
|
+
apiVersion: apps/v1
|
|
16
|
+
kind: Deployment
|
|
17
|
+
metadata:
|
|
18
|
+
name: myapp
|
|
19
|
+
labels:
|
|
20
|
+
app: myapp
|
|
21
|
+
spec:
|
|
22
|
+
replicas: 3
|
|
23
|
+
selector:
|
|
24
|
+
matchLabels:
|
|
25
|
+
app: myapp
|
|
26
|
+
template:
|
|
27
|
+
metadata:
|
|
28
|
+
labels:
|
|
29
|
+
app: myapp
|
|
30
|
+
spec:
|
|
31
|
+
containers:
|
|
32
|
+
- name: myapp
|
|
33
|
+
image: myacr.azurecr.io/myapp:v1
|
|
34
|
+
ports:
|
|
35
|
+
- containerPort: 80
|
|
36
|
+
resources:
|
|
37
|
+
requests:
|
|
38
|
+
memory: "128Mi"
|
|
39
|
+
cpu: "100m"
|
|
40
|
+
limits:
|
|
41
|
+
memory: "256Mi"
|
|
42
|
+
cpu: "200m"
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
## Service
|
|
48
|
+
|
|
49
|
+
```yaml
|
|
50
|
+
apiVersion: v1
|
|
51
|
+
kind: Service
|
|
52
|
+
metadata:
|
|
53
|
+
name: myapp-service
|
|
54
|
+
spec:
|
|
55
|
+
selector:
|
|
56
|
+
app: myapp
|
|
57
|
+
ports:
|
|
58
|
+
- port: 80
|
|
59
|
+
targetPort: 80
|
|
60
|
+
type: LoadBalancer
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
---
|
|
64
|
+
|
|
65
|
+
## Ingress
|
|
66
|
+
|
|
67
|
+
```yaml
|
|
68
|
+
apiVersion: networking.k8s.io/v1
|
|
69
|
+
kind: Ingress
|
|
70
|
+
metadata:
|
|
71
|
+
name: myapp-ingress
|
|
72
|
+
spec:
|
|
73
|
+
rules:
|
|
74
|
+
- host: myapp.example.com
|
|
75
|
+
http:
|
|
76
|
+
paths:
|
|
77
|
+
- path: /
|
|
78
|
+
pathType: Prefix
|
|
79
|
+
backend:
|
|
80
|
+
service:
|
|
81
|
+
name: myapp-service
|
|
82
|
+
port:
|
|
83
|
+
number: 80
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
---
|
|
87
|
+
|
|
88
|
+
## ConfigMap & Secrets
|
|
89
|
+
|
|
90
|
+
```yaml
|
|
91
|
+
apiVersion: v1
|
|
92
|
+
kind: ConfigMap
|
|
93
|
+
metadata:
|
|
94
|
+
name: myapp-config
|
|
95
|
+
data:
|
|
96
|
+
ENVIRONMENT: "production"
|
|
97
|
+
|
|
98
|
+
---
|
|
99
|
+
apiVersion: v1
|
|
100
|
+
kind: Secret
|
|
101
|
+
metadata:
|
|
102
|
+
name: myapp-secrets
|
|
103
|
+
type: Opaque
|
|
104
|
+
data:
|
|
105
|
+
CONNECTION_STRING: <base64-encoded>
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
---
|
|
109
|
+
|
|
110
|
+
## Health Checks
|
|
111
|
+
|
|
112
|
+
```yaml
|
|
113
|
+
livenessProbe:
|
|
114
|
+
httpGet:
|
|
115
|
+
path: /health
|
|
116
|
+
port: 80
|
|
117
|
+
initialDelaySeconds: 10
|
|
118
|
+
periodSeconds: 5
|
|
119
|
+
|
|
120
|
+
readinessProbe:
|
|
121
|
+
httpGet:
|
|
122
|
+
path: /ready
|
|
123
|
+
port: 80
|
|
124
|
+
initialDelaySeconds: 5
|
|
125
|
+
periodSeconds: 3
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
---
|
|
129
|
+
|
|
130
|
+
## DO / DON'T
|
|
131
|
+
|
|
132
|
+
| ✅ Do | ❌ Don't |
|
|
133
|
+
|-------|---------|
|
|
134
|
+
| Resource limits | Unlimited resources |
|
|
135
|
+
| Health checks | Skip probes |
|
|
136
|
+
| Rolling updates | Recreate strategy |
|