superkit-mcp-server 1.0.1 → 1.0.2
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/ARCHITECTURE.md +2 -3
- package/README.md +1 -0
- package/build/index.js +75 -0
- package/build/tools/autoPreview.js +99 -0
- package/build/tools/checklist.js +120 -0
- package/build/tools/sessionManager.js +107 -0
- package/build/tools/validators/__tests__/apiSchema.test.js +77 -0
- package/build/tools/validators/__tests__/convertRules.test.js +38 -0
- package/build/tools/validators/__tests__/frontendDesign.test.js +55 -0
- package/build/tools/validators/__tests__/geoChecker.test.js +45 -0
- package/build/tools/validators/__tests__/i18nChecker.test.js +32 -0
- package/build/tools/validators/__tests__/lintRunner.test.js +65 -0
- package/build/tools/validators/__tests__/mobileAudit.test.js +40 -0
- package/build/tools/validators/__tests__/playwrightRunner.test.js +55 -0
- package/build/tools/validators/__tests__/reactPerformanceChecker.test.js +49 -0
- package/build/tools/validators/__tests__/securityScan.test.js +42 -0
- package/build/tools/validators/__tests__/seoChecker.test.js +44 -0
- package/build/tools/validators/__tests__/testRunner.test.js +49 -0
- package/build/tools/validators/__tests__/typeCoverage.test.js +62 -0
- package/build/tools/validators/accessibilityChecker.js +124 -0
- package/build/tools/validators/apiValidator.js +140 -0
- package/build/tools/validators/convertRules.js +170 -0
- package/build/tools/validators/geoChecker.js +176 -0
- package/build/tools/validators/i18nChecker.js +205 -0
- package/build/tools/validators/lighthouseAudit.js +50 -0
- package/build/tools/validators/lintRunner.js +106 -0
- package/build/tools/validators/mobileAudit.js +190 -0
- package/build/tools/validators/playwrightRunner.js +101 -0
- package/build/tools/validators/reactPerformanceChecker.js +199 -0
- package/build/tools/validators/schemaValidator.js +105 -0
- package/build/tools/validators/securityScan.js +215 -0
- package/build/tools/validators/seoChecker.js +122 -0
- package/build/tools/validators/testRunner.js +111 -0
- package/build/tools/validators/typeCoverage.js +150 -0
- package/build/tools/validators/uxAudit.js +222 -0
- package/build/tools/verifyAll.js +159 -0
- package/package.json +5 -3
- package/skills/tech/api-patterns/SKILL.md +1 -1
- package/skills/tech/clean-code/SKILL.md +14 -14
- package/skills/tech/doc.md +3 -3
- package/skills/tech/frontend-design/SKILL.md +1 -1
- package/skills/tech/geo-fundamentals/SKILL.md +1 -1
- package/skills/tech/i18n-localization/SKILL.md +1 -1
- package/skills/tech/lint-and-validate/SKILL.md +2 -2
- package/skills/tech/mobile-design/SKILL.md +1 -1
- package/skills/tech/nextjs-react-expert/SKILL.md +1 -1
- package/skills/tech/parallel-agents/SKILL.md +3 -3
- package/skills/tech/performance-profiling/SKILL.md +1 -1
- package/skills/tech/vulnerability-scanner/SKILL.md +1 -1
- package/skills/tech/webapp-testing/SKILL.md +3 -3
- package/workflows/review-compound.md +1 -1
- package/skills/tech/api-patterns/scripts/api_validator.py +0 -211
- package/skills/tech/database-design/scripts/schema_validator.py +0 -172
- package/skills/tech/frontend-design/scripts/accessibility_checker.py +0 -183
- package/skills/tech/frontend-design/scripts/ux_audit.py +0 -722
- package/skills/tech/geo-fundamentals/scripts/geo_checker.py +0 -289
- package/skills/tech/i18n-localization/scripts/i18n_checker.py +0 -241
- package/skills/tech/lint-and-validate/scripts/lint_runner.py +0 -184
- package/skills/tech/lint-and-validate/scripts/type_coverage.py +0 -173
- package/skills/tech/mobile-design/scripts/mobile_audit.py +0 -670
- package/skills/tech/nextjs-react-expert/scripts/convert_rules.py +0 -222
- package/skills/tech/nextjs-react-expert/scripts/react_performance_checker.py +0 -252
- package/skills/tech/performance-profiling/scripts/lighthouse_audit.py +0 -76
- package/skills/tech/seo-fundamentals/scripts/seo_checker.py +0 -219
- package/skills/tech/testing-patterns/scripts/test_runner.py +0 -219
- package/skills/tech/vulnerability-scanner/scripts/security_scan.py +0 -458
- package/skills/tech/webapp-testing/scripts/playwright_runner.py +0 -173
|
@@ -147,20 +147,20 @@ File to edit: UserService.ts
|
|
|
147
147
|
|
|
148
148
|
| Agent | Script | Command |
|
|
149
149
|
|-------|--------|---------|
|
|
150
|
-
| **frontend-specialist** | UX Audit | `
|
|
151
|
-
| **frontend-specialist** | A11y Check | `
|
|
152
|
-
| **backend-specialist** | API Validator | `
|
|
153
|
-
| **mobile-developer** | Mobile Audit | `
|
|
154
|
-
| **database-architect** | Schema Validate | `
|
|
155
|
-
| **security-auditor** | Security Scan | `
|
|
156
|
-
| **seo-specialist** | SEO Check | `
|
|
157
|
-
| **seo-specialist** | GEO Check | `
|
|
158
|
-
| **performance-optimizer** | Lighthouse | `
|
|
159
|
-
| **test-engineer** | Test Runner | `
|
|
160
|
-
| **test-engineer** | Playwright | `
|
|
161
|
-
| **Any agent** | Lint Check | `
|
|
162
|
-
| **Any agent** | Type Coverage | `
|
|
163
|
-
| **Any agent** | i18n Check | `
|
|
150
|
+
| **frontend-specialist** | UX Audit | `MCP Tool 'call_tool_checklist' .` |
|
|
151
|
+
| **frontend-specialist** | A11y Check | `MCP Tool 'call_tool_checklist' .` |
|
|
152
|
+
| **backend-specialist** | API Validator | `MCP Tool 'call_tool_checklist' .` |
|
|
153
|
+
| **mobile-developer** | Mobile Audit | `MCP Tool 'call_tool_checklist' .` |
|
|
154
|
+
| **database-architect** | Schema Validate | `MCP Tool 'call_tool_checklist' .` |
|
|
155
|
+
| **security-auditor** | Security Scan | `MCP Tool 'call_tool_checklist' .` |
|
|
156
|
+
| **seo-specialist** | SEO Check | `MCP Tool 'call_tool_checklist' .` |
|
|
157
|
+
| **seo-specialist** | GEO Check | `MCP Tool 'call_tool_checklist' .` |
|
|
158
|
+
| **performance-optimizer** | Lighthouse | `MCP Tool 'call_tool_checklist' <url>` |
|
|
159
|
+
| **test-engineer** | Test Runner | `MCP Tool 'call_tool_checklist' .` |
|
|
160
|
+
| **test-engineer** | Playwright | `MCP Tool 'call_tool_checklist' <url>` |
|
|
161
|
+
| **Any agent** | Lint Check | `MCP Tool 'call_tool_checklist' .` |
|
|
162
|
+
| **Any agent** | Type Coverage | `MCP Tool 'call_tool_checklist' .` |
|
|
163
|
+
| **Any agent** | i18n Check | `MCP Tool 'call_tool_checklist' .` |
|
|
164
164
|
|
|
165
165
|
> ❌ **WRONG:** `test-engineer` running `ux_audit.py`
|
|
166
166
|
> ✅ **CORRECT:** `frontend-specialist` running `ux_audit.py`
|
package/skills/tech/doc.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Super Kit Skills
|
|
2
2
|
|
|
3
3
|
> **Guide to creating and using Skills in the Super Kit**
|
|
4
4
|
|
|
@@ -6,9 +6,9 @@
|
|
|
6
6
|
|
|
7
7
|
## 📋 Overview
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
Base models (like Gemini) are powerful generalists, they don't know your specific project context or your team's standards. Loading every rule or tool into the agent's context window leads to "tool bloat," higher costs, latency, and confusion.
|
|
10
10
|
|
|
11
|
-
**
|
|
11
|
+
**Super Kit Skills** solve this through **Progressive Disclosure**. A Skill is a package of specialized knowledge that remains dormant until needed. This information is only loaded into the agent's context when your specific request matches the skill's description.
|
|
12
12
|
|
|
13
13
|
---
|
|
14
14
|
|
|
@@ -35,7 +35,7 @@ allowed-tools: Read, Write, Edit, Glob, Grep, Bash
|
|
|
35
35
|
|
|
36
36
|
| Script | Purpose | Usage |
|
|
37
37
|
|--------|---------|-------|
|
|
38
|
-
| `
|
|
38
|
+
| `ux_audit` validator | UX Psychology & Accessibility Audit | `call_tool_checklist` |
|
|
39
39
|
|
|
40
40
|
---
|
|
41
41
|
|
|
@@ -152,5 +152,5 @@ How AI engines select content to cite:
|
|
|
152
152
|
|
|
153
153
|
| Script | Purpose | Command |
|
|
154
154
|
|--------|---------|---------|
|
|
155
|
-
| `
|
|
155
|
+
| `geo_checker` validator | GEO audit (AI citation readiness) | `call_tool_checklist` |
|
|
156
156
|
|
|
@@ -151,4 +151,4 @@ Before shipping:
|
|
|
151
151
|
|
|
152
152
|
| Script | Purpose | Command |
|
|
153
153
|
|--------|---------|---------|
|
|
154
|
-
| `
|
|
154
|
+
| `i18n_checker` validator | Detect hardcoded strings & missing translations | `call_tool_checklist` |
|
|
@@ -40,6 +40,6 @@ allowed-tools: Read, Glob, Grep, Bash
|
|
|
40
40
|
|
|
41
41
|
| Script | Purpose | Command |
|
|
42
42
|
|--------|---------|---------|
|
|
43
|
-
| `
|
|
44
|
-
| `
|
|
43
|
+
| `lint_runner` validator | Unified lint check | `call_tool_checklist` |
|
|
44
|
+
| `type_coverage` validator | Type coverage analysis | `call_tool_checklist` |
|
|
45
45
|
|
|
@@ -17,7 +17,7 @@ allowed-tools: Read, Glob, Grep, Bash
|
|
|
17
17
|
|
|
18
18
|
| Script | Purpose | Usage |
|
|
19
19
|
|--------|---------|-------|
|
|
20
|
-
| `
|
|
20
|
+
| `mobile_audit` validator | Mobile UX & Touch Audit | `call_tool_checklist` |
|
|
21
21
|
|
|
22
22
|
---
|
|
23
23
|
|
|
@@ -212,7 +212,7 @@ Before shipping to production:
|
|
|
212
212
|
|
|
213
213
|
| Script | Purpose | Command |
|
|
214
214
|
| -------------------------------------- | --------------------------- | ------------------------------------------------------------ |
|
|
215
|
-
| `
|
|
215
|
+
| `react_performance_checker` validator | Automated performance audit | `call_tool_checklist` |
|
|
216
216
|
|
|
217
217
|
---
|
|
218
218
|
|
|
@@ -6,11 +6,11 @@ allowed-tools: Read, Glob, Grep
|
|
|
6
6
|
|
|
7
7
|
# Native Parallel Agents
|
|
8
8
|
|
|
9
|
-
> Orchestration through
|
|
9
|
+
> Orchestration through native Agent tools
|
|
10
10
|
|
|
11
11
|
## Overview
|
|
12
12
|
|
|
13
|
-
This skill enables coordinating multiple specialized agents through
|
|
13
|
+
This skill enables coordinating multiple specialized agents through your AI's native sub-agent system. Unlike external scripts, this approach keeps all orchestration within the primary agent's control.
|
|
14
14
|
|
|
15
15
|
## When to Use Orchestration
|
|
16
16
|
|
|
@@ -113,7 +113,7 @@ Agents: security-auditor → penetration-tester → synthesis
|
|
|
113
113
|
|
|
114
114
|
---
|
|
115
115
|
|
|
116
|
-
##
|
|
116
|
+
## Native Built-in Agents
|
|
117
117
|
|
|
118
118
|
These work alongside custom agents:
|
|
119
119
|
|
|
@@ -14,7 +14,7 @@ allowed-tools: Read, Glob, Grep, Bash
|
|
|
14
14
|
|
|
15
15
|
| Script | Purpose | Usage |
|
|
16
16
|
|--------|---------|-------|
|
|
17
|
-
| `
|
|
17
|
+
| `lighthouse_audit` validator | Lighthouse performance audit | `call_tool_checklist` |
|
|
18
18
|
|
|
19
19
|
---
|
|
20
20
|
|
|
@@ -14,7 +14,7 @@ allowed-tools: Read, Glob, Grep, Bash
|
|
|
14
14
|
|
|
15
15
|
| Script | Purpose | Usage |
|
|
16
16
|
|--------|---------|-------|
|
|
17
|
-
| `
|
|
17
|
+
| `security_scan` validator | Validate security principles applied | `call_tool_checklist` |
|
|
18
18
|
|
|
19
19
|
## 📋 Reference Files
|
|
20
20
|
|
|
@@ -14,9 +14,9 @@ allowed-tools: Read, Write, Edit, Glob, Grep, Bash
|
|
|
14
14
|
|
|
15
15
|
| Script | Purpose | Usage |
|
|
16
16
|
|--------|---------|-------|
|
|
17
|
-
| `
|
|
18
|
-
| | With screenshot | `
|
|
19
|
-
| | Accessibility check | `
|
|
17
|
+
| `playwright_runner` validator | Basic browser test | `call_tool_checklist` |
|
|
18
|
+
| | With screenshot | `call_tool_checklist` |
|
|
19
|
+
| | Accessibility check | `call_tool_checklist` |
|
|
20
20
|
|
|
21
21
|
**Requires:** `pip install playwright && playwright install chromium`
|
|
22
22
|
|
|
@@ -6,7 +6,7 @@ description: (Compound) Perform comprehensive multi-pass code review with securi
|
|
|
6
6
|
|
|
7
7
|
Perform exhaustive code reviews using multi-perspective analysis to catch issues before they ship.
|
|
8
8
|
|
|
9
|
-
> **
|
|
9
|
+
> **Sequential Review:** Unlike parallel agent systems, this review runs sequentially through each review perspective. Focus on depth over breadth.
|
|
10
10
|
>
|
|
11
11
|
> **Note:** This is the Compound version with multi-pass review. For quick review, use `/review`.
|
|
12
12
|
|
|
@@ -1,211 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env python3
|
|
2
|
-
"""
|
|
3
|
-
API Validator - Checks API endpoints for best practices.
|
|
4
|
-
Validates OpenAPI specs, response formats, and common issues.
|
|
5
|
-
"""
|
|
6
|
-
import sys
|
|
7
|
-
import json
|
|
8
|
-
import re
|
|
9
|
-
from pathlib import Path
|
|
10
|
-
|
|
11
|
-
# Fix Windows console encoding for Unicode output
|
|
12
|
-
try:
|
|
13
|
-
sys.stdout.reconfigure(encoding='utf-8', errors='replace')
|
|
14
|
-
sys.stderr.reconfigure(encoding='utf-8', errors='replace')
|
|
15
|
-
except AttributeError:
|
|
16
|
-
pass # Python < 3.7
|
|
17
|
-
|
|
18
|
-
def find_api_files(project_path: Path) -> list:
|
|
19
|
-
"""Find API-related files."""
|
|
20
|
-
patterns = [
|
|
21
|
-
"**/*api*.ts", "**/*api*.js", "**/*api*.py",
|
|
22
|
-
"**/routes/*.ts", "**/routes/*.js", "**/routes/*.py",
|
|
23
|
-
"**/controllers/*.ts", "**/controllers/*.js",
|
|
24
|
-
"**/endpoints/*.ts", "**/endpoints/*.py",
|
|
25
|
-
"**/*.openapi.json", "**/*.openapi.yaml",
|
|
26
|
-
"**/swagger.json", "**/swagger.yaml",
|
|
27
|
-
"**/openapi.json", "**/openapi.yaml"
|
|
28
|
-
]
|
|
29
|
-
|
|
30
|
-
files = []
|
|
31
|
-
for pattern in patterns:
|
|
32
|
-
files.extend(project_path.glob(pattern))
|
|
33
|
-
|
|
34
|
-
# Exclude node_modules, etc.
|
|
35
|
-
return [f for f in files if not any(x in str(f) for x in ['node_modules', '.git', 'dist', 'build', '__pycache__'])]
|
|
36
|
-
|
|
37
|
-
def check_openapi_spec(file_path: Path) -> dict:
|
|
38
|
-
"""Check OpenAPI/Swagger specification."""
|
|
39
|
-
issues = []
|
|
40
|
-
passed = []
|
|
41
|
-
|
|
42
|
-
try:
|
|
43
|
-
content = file_path.read_text(encoding='utf-8')
|
|
44
|
-
|
|
45
|
-
if file_path.suffix == '.json':
|
|
46
|
-
spec = json.loads(content)
|
|
47
|
-
else:
|
|
48
|
-
# Basic YAML check
|
|
49
|
-
if 'openapi:' in content or 'swagger:' in content:
|
|
50
|
-
passed.append("[OK] OpenAPI/Swagger version defined")
|
|
51
|
-
else:
|
|
52
|
-
issues.append("[X] No OpenAPI version found")
|
|
53
|
-
|
|
54
|
-
if 'paths:' in content:
|
|
55
|
-
passed.append("[OK] Paths section exists")
|
|
56
|
-
else:
|
|
57
|
-
issues.append("[X] No paths defined")
|
|
58
|
-
|
|
59
|
-
if 'components:' in content or 'definitions:' in content:
|
|
60
|
-
passed.append("[OK] Schema components defined")
|
|
61
|
-
|
|
62
|
-
return {'file': str(file_path), 'passed': passed, 'issues': issues, 'type': 'openapi'}
|
|
63
|
-
|
|
64
|
-
# JSON OpenAPI checks
|
|
65
|
-
if 'openapi' in spec or 'swagger' in spec:
|
|
66
|
-
passed.append("[OK] OpenAPI version defined")
|
|
67
|
-
|
|
68
|
-
if 'info' in spec:
|
|
69
|
-
if 'title' in spec['info']:
|
|
70
|
-
passed.append("[OK] API title defined")
|
|
71
|
-
if 'version' in spec['info']:
|
|
72
|
-
passed.append("[OK] API version defined")
|
|
73
|
-
if 'description' not in spec['info']:
|
|
74
|
-
issues.append("[!] API description missing")
|
|
75
|
-
|
|
76
|
-
if 'paths' in spec:
|
|
77
|
-
path_count = len(spec['paths'])
|
|
78
|
-
passed.append(f"[OK] {path_count} endpoints defined")
|
|
79
|
-
|
|
80
|
-
# Check each path
|
|
81
|
-
for path, methods in spec['paths'].items():
|
|
82
|
-
for method, details in methods.items():
|
|
83
|
-
if method in ['get', 'post', 'put', 'patch', 'delete']:
|
|
84
|
-
if 'responses' not in details:
|
|
85
|
-
issues.append(f"[X] {method.upper()} {path}: No responses defined")
|
|
86
|
-
if 'summary' not in details and 'description' not in details:
|
|
87
|
-
issues.append(f"[!] {method.upper()} {path}: No description")
|
|
88
|
-
|
|
89
|
-
except Exception as e:
|
|
90
|
-
issues.append(f"[X] Parse error: {e}")
|
|
91
|
-
|
|
92
|
-
return {'file': str(file_path), 'passed': passed, 'issues': issues, 'type': 'openapi'}
|
|
93
|
-
|
|
94
|
-
def check_api_code(file_path: Path) -> dict:
|
|
95
|
-
"""Check API code for common issues."""
|
|
96
|
-
issues = []
|
|
97
|
-
passed = []
|
|
98
|
-
|
|
99
|
-
try:
|
|
100
|
-
content = file_path.read_text(encoding='utf-8')
|
|
101
|
-
|
|
102
|
-
# Check for error handling
|
|
103
|
-
error_patterns = [
|
|
104
|
-
r'try\s*{', r'try:', r'\.catch\(',
|
|
105
|
-
r'except\s+', r'catch\s*\('
|
|
106
|
-
]
|
|
107
|
-
has_error_handling = any(re.search(p, content) for p in error_patterns)
|
|
108
|
-
if has_error_handling:
|
|
109
|
-
passed.append("[OK] Error handling present")
|
|
110
|
-
else:
|
|
111
|
-
issues.append("[X] No error handling found")
|
|
112
|
-
|
|
113
|
-
# Check for status codes
|
|
114
|
-
status_patterns = [
|
|
115
|
-
r'status\s*\(\s*\d{3}\s*\)', r'statusCode\s*[=:]\s*\d{3}',
|
|
116
|
-
r'HttpStatus\.', r'status_code\s*=\s*\d{3}',
|
|
117
|
-
r'\.status\(\d{3}\)', r'res\.status\('
|
|
118
|
-
]
|
|
119
|
-
has_status = any(re.search(p, content) for p in status_patterns)
|
|
120
|
-
if has_status:
|
|
121
|
-
passed.append("[OK] HTTP status codes used")
|
|
122
|
-
else:
|
|
123
|
-
issues.append("[!] No explicit HTTP status codes")
|
|
124
|
-
|
|
125
|
-
# Check for validation
|
|
126
|
-
validation_patterns = [
|
|
127
|
-
r'validate', r'schema', r'zod', r'joi', r'yup',
|
|
128
|
-
r'pydantic', r'@Body\(', r'@Query\('
|
|
129
|
-
]
|
|
130
|
-
has_validation = any(re.search(p, content, re.I) for p in validation_patterns)
|
|
131
|
-
if has_validation:
|
|
132
|
-
passed.append("[OK] Input validation present")
|
|
133
|
-
else:
|
|
134
|
-
issues.append("[!] No input validation detected")
|
|
135
|
-
|
|
136
|
-
# Check for auth middleware
|
|
137
|
-
auth_patterns = [
|
|
138
|
-
r'auth', r'jwt', r'bearer', r'token',
|
|
139
|
-
r'middleware', r'guard', r'@Authenticated'
|
|
140
|
-
]
|
|
141
|
-
has_auth = any(re.search(p, content, re.I) for p in auth_patterns)
|
|
142
|
-
if has_auth:
|
|
143
|
-
passed.append("[OK] Authentication/authorization detected")
|
|
144
|
-
|
|
145
|
-
# Check for rate limiting
|
|
146
|
-
rate_patterns = [r'rateLimit', r'throttle', r'rate.?limit']
|
|
147
|
-
has_rate = any(re.search(p, content, re.I) for p in rate_patterns)
|
|
148
|
-
if has_rate:
|
|
149
|
-
passed.append("[OK] Rate limiting present")
|
|
150
|
-
|
|
151
|
-
# Check for logging
|
|
152
|
-
log_patterns = [r'console\.log', r'logger\.', r'logging\.', r'log\.']
|
|
153
|
-
has_logging = any(re.search(p, content) for p in log_patterns)
|
|
154
|
-
if has_logging:
|
|
155
|
-
passed.append("[OK] Logging present")
|
|
156
|
-
|
|
157
|
-
except Exception as e:
|
|
158
|
-
issues.append(f"[X] Read error: {e}")
|
|
159
|
-
|
|
160
|
-
return {'file': str(file_path), 'passed': passed, 'issues': issues, 'type': 'code'}
|
|
161
|
-
|
|
162
|
-
def main():
|
|
163
|
-
target = sys.argv[1] if len(sys.argv) > 1 else "."
|
|
164
|
-
project_path = Path(target)
|
|
165
|
-
|
|
166
|
-
print("\n" + "=" * 60)
|
|
167
|
-
print(" API VALIDATOR - Endpoint Best Practices Check")
|
|
168
|
-
print("=" * 60 + "\n")
|
|
169
|
-
|
|
170
|
-
api_files = find_api_files(project_path)
|
|
171
|
-
|
|
172
|
-
if not api_files:
|
|
173
|
-
print("[!] No API files found.")
|
|
174
|
-
print(" Looking for: routes/, controllers/, api/, openapi.json/yaml")
|
|
175
|
-
sys.exit(0)
|
|
176
|
-
|
|
177
|
-
results = []
|
|
178
|
-
for file_path in api_files[:15]: # Limit
|
|
179
|
-
if 'openapi' in file_path.name.lower() or 'swagger' in file_path.name.lower():
|
|
180
|
-
result = check_openapi_spec(file_path)
|
|
181
|
-
else:
|
|
182
|
-
result = check_api_code(file_path)
|
|
183
|
-
results.append(result)
|
|
184
|
-
|
|
185
|
-
# Print results
|
|
186
|
-
total_issues = 0
|
|
187
|
-
total_passed = 0
|
|
188
|
-
|
|
189
|
-
for result in results:
|
|
190
|
-
print(f"\n[FILE] {result['file']} [{result['type']}]")
|
|
191
|
-
for item in result['passed']:
|
|
192
|
-
print(f" {item}")
|
|
193
|
-
total_passed += 1
|
|
194
|
-
for item in result['issues']:
|
|
195
|
-
print(f" {item}")
|
|
196
|
-
if item.startswith("[X]"):
|
|
197
|
-
total_issues += 1
|
|
198
|
-
|
|
199
|
-
print("\n" + "=" * 60)
|
|
200
|
-
print(f"[RESULTS] {total_passed} passed, {total_issues} critical issues")
|
|
201
|
-
print("=" * 60)
|
|
202
|
-
|
|
203
|
-
if total_issues == 0:
|
|
204
|
-
print("[OK] API validation passed")
|
|
205
|
-
sys.exit(0)
|
|
206
|
-
else:
|
|
207
|
-
print("[X] Fix critical issues before deployment")
|
|
208
|
-
sys.exit(1)
|
|
209
|
-
|
|
210
|
-
if __name__ == "__main__":
|
|
211
|
-
main()
|
|
@@ -1,172 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env python3
|
|
2
|
-
"""
|
|
3
|
-
Schema Validator - Database schema validation
|
|
4
|
-
Validates Prisma schemas and checks for common issues.
|
|
5
|
-
|
|
6
|
-
Usage:
|
|
7
|
-
python schema_validator.py <project_path>
|
|
8
|
-
|
|
9
|
-
Checks:
|
|
10
|
-
- Prisma schema syntax
|
|
11
|
-
- Missing relations
|
|
12
|
-
- Index recommendations
|
|
13
|
-
- Naming conventions
|
|
14
|
-
"""
|
|
15
|
-
|
|
16
|
-
import sys
|
|
17
|
-
import json
|
|
18
|
-
import re
|
|
19
|
-
from pathlib import Path
|
|
20
|
-
from datetime import datetime
|
|
21
|
-
|
|
22
|
-
# Fix Windows console encoding
|
|
23
|
-
try:
|
|
24
|
-
sys.stdout.reconfigure(encoding='utf-8', errors='replace')
|
|
25
|
-
except:
|
|
26
|
-
pass
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
def find_schema_files(project_path: Path) -> list:
|
|
30
|
-
"""Find database schema files."""
|
|
31
|
-
schemas = []
|
|
32
|
-
|
|
33
|
-
# Prisma schema
|
|
34
|
-
prisma_files = list(project_path.glob('**/prisma/schema.prisma'))
|
|
35
|
-
schemas.extend([('prisma', f) for f in prisma_files])
|
|
36
|
-
|
|
37
|
-
# Drizzle schema files
|
|
38
|
-
drizzle_files = list(project_path.glob('**/drizzle/*.ts'))
|
|
39
|
-
drizzle_files.extend(project_path.glob('**/schema/*.ts'))
|
|
40
|
-
for f in drizzle_files:
|
|
41
|
-
if 'schema' in f.name.lower() or 'table' in f.name.lower():
|
|
42
|
-
schemas.append(('drizzle', f))
|
|
43
|
-
|
|
44
|
-
return schemas[:10] # Limit
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
def validate_prisma_schema(file_path: Path) -> list:
|
|
48
|
-
"""Validate Prisma schema file."""
|
|
49
|
-
issues = []
|
|
50
|
-
|
|
51
|
-
try:
|
|
52
|
-
content = file_path.read_text(encoding='utf-8', errors='ignore')
|
|
53
|
-
|
|
54
|
-
# Find all models
|
|
55
|
-
models = re.findall(r'model\s+(\w+)\s*{([^}]+)}', content, re.DOTALL)
|
|
56
|
-
|
|
57
|
-
for model_name, model_body in models:
|
|
58
|
-
# Check naming convention (PascalCase)
|
|
59
|
-
if not model_name[0].isupper():
|
|
60
|
-
issues.append(f"Model '{model_name}' should be PascalCase")
|
|
61
|
-
|
|
62
|
-
# Check for id field
|
|
63
|
-
if '@id' not in model_body and 'id' not in model_body.lower():
|
|
64
|
-
issues.append(f"Model '{model_name}' might be missing @id field")
|
|
65
|
-
|
|
66
|
-
# Check for createdAt/updatedAt
|
|
67
|
-
if 'createdAt' not in model_body and 'created_at' not in model_body:
|
|
68
|
-
issues.append(f"Model '{model_name}' missing createdAt field (recommended)")
|
|
69
|
-
|
|
70
|
-
# Check for @relation without fields
|
|
71
|
-
relations = re.findall(r'@relation\([^)]*\)', model_body)
|
|
72
|
-
for rel in relations:
|
|
73
|
-
if 'fields:' not in rel and 'references:' not in rel:
|
|
74
|
-
pass # Implicit relation, ok
|
|
75
|
-
|
|
76
|
-
# Check for @@index suggestions
|
|
77
|
-
foreign_keys = re.findall(r'(\w+Id)\s+\w+', model_body)
|
|
78
|
-
for fk in foreign_keys:
|
|
79
|
-
if f'@@index([{fk}])' not in content and f'@@index(["{fk}"])' not in content:
|
|
80
|
-
issues.append(f"Consider adding @@index([{fk}]) for better query performance in {model_name}")
|
|
81
|
-
|
|
82
|
-
# Check for enum definitions
|
|
83
|
-
enums = re.findall(r'enum\s+(\w+)\s*{', content)
|
|
84
|
-
for enum_name in enums:
|
|
85
|
-
if not enum_name[0].isupper():
|
|
86
|
-
issues.append(f"Enum '{enum_name}' should be PascalCase")
|
|
87
|
-
|
|
88
|
-
except Exception as e:
|
|
89
|
-
issues.append(f"Error reading schema: {str(e)[:50]}")
|
|
90
|
-
|
|
91
|
-
return issues
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
def main():
|
|
95
|
-
project_path = Path(sys.argv[1] if len(sys.argv) > 1 else ".").resolve()
|
|
96
|
-
|
|
97
|
-
print(f"\n{'='*60}")
|
|
98
|
-
print(f"[SCHEMA VALIDATOR] Database Schema Validation")
|
|
99
|
-
print(f"{'='*60}")
|
|
100
|
-
print(f"Project: {project_path}")
|
|
101
|
-
print(f"Time: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
|
|
102
|
-
print("-"*60)
|
|
103
|
-
|
|
104
|
-
# Find schema files
|
|
105
|
-
schemas = find_schema_files(project_path)
|
|
106
|
-
print(f"Found {len(schemas)} schema files")
|
|
107
|
-
|
|
108
|
-
if not schemas:
|
|
109
|
-
output = {
|
|
110
|
-
"script": "schema_validator",
|
|
111
|
-
"project": str(project_path),
|
|
112
|
-
"schemas_checked": 0,
|
|
113
|
-
"issues_found": 0,
|
|
114
|
-
"passed": True,
|
|
115
|
-
"message": "No schema files found"
|
|
116
|
-
}
|
|
117
|
-
print(json.dumps(output, indent=2))
|
|
118
|
-
sys.exit(0)
|
|
119
|
-
|
|
120
|
-
# Validate each schema
|
|
121
|
-
all_issues = []
|
|
122
|
-
|
|
123
|
-
for schema_type, file_path in schemas:
|
|
124
|
-
print(f"\nValidating: {file_path.name} ({schema_type})")
|
|
125
|
-
|
|
126
|
-
if schema_type == 'prisma':
|
|
127
|
-
issues = validate_prisma_schema(file_path)
|
|
128
|
-
else:
|
|
129
|
-
issues = [] # Drizzle validation could be added
|
|
130
|
-
|
|
131
|
-
if issues:
|
|
132
|
-
all_issues.append({
|
|
133
|
-
"file": str(file_path.name),
|
|
134
|
-
"type": schema_type,
|
|
135
|
-
"issues": issues
|
|
136
|
-
})
|
|
137
|
-
|
|
138
|
-
# Summary
|
|
139
|
-
print("\n" + "="*60)
|
|
140
|
-
print("SCHEMA ISSUES")
|
|
141
|
-
print("="*60)
|
|
142
|
-
|
|
143
|
-
if all_issues:
|
|
144
|
-
for item in all_issues:
|
|
145
|
-
print(f"\n{item['file']} ({item['type']}):")
|
|
146
|
-
for issue in item["issues"][:5]: # Limit per file
|
|
147
|
-
print(f" - {issue}")
|
|
148
|
-
if len(item["issues"]) > 5:
|
|
149
|
-
print(f" ... and {len(item['issues']) - 5} more issues")
|
|
150
|
-
else:
|
|
151
|
-
print("No schema issues found!")
|
|
152
|
-
|
|
153
|
-
total_issues = sum(len(item["issues"]) for item in all_issues)
|
|
154
|
-
# Schema issues are warnings, not failures
|
|
155
|
-
passed = True
|
|
156
|
-
|
|
157
|
-
output = {
|
|
158
|
-
"script": "schema_validator",
|
|
159
|
-
"project": str(project_path),
|
|
160
|
-
"schemas_checked": len(schemas),
|
|
161
|
-
"issues_found": total_issues,
|
|
162
|
-
"passed": passed,
|
|
163
|
-
"issues": all_issues
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
print("\n" + json.dumps(output, indent=2))
|
|
167
|
-
|
|
168
|
-
sys.exit(0)
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
if __name__ == "__main__":
|
|
172
|
-
main()
|