@vibecheckai/cli 3.4.0 → 3.5.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/bin/registry.js +243 -152
- package/bin/runners/cli-utils.js +2 -33
- package/bin/runners/context/generators/cursor.js +49 -2
- package/bin/runners/lib/agent-firewall/learning/learning-engine.js +849 -0
- package/bin/runners/lib/analyzers.js +544 -19
- package/bin/runners/lib/audit-logger.js +532 -0
- package/bin/runners/lib/authority/authorities/architecture.js +364 -0
- package/bin/runners/lib/authority/authorities/compliance.js +341 -0
- package/bin/runners/lib/authority/authorities/human.js +343 -0
- package/bin/runners/lib/authority/authorities/quality.js +420 -0
- package/bin/runners/lib/authority/authorities/security.js +228 -0
- package/bin/runners/lib/authority/index.js +293 -0
- package/bin/runners/lib/authority-badge.js +425 -425
- package/bin/runners/lib/bundle/bundle-intelligence.js +846 -0
- package/bin/runners/lib/cli-charts.js +368 -0
- package/bin/runners/lib/cli-config-display.js +405 -0
- package/bin/runners/lib/cli-demo.js +275 -0
- package/bin/runners/lib/cli-errors.js +438 -0
- package/bin/runners/lib/cli-help-formatter.js +439 -0
- package/bin/runners/lib/cli-interactive-menu.js +509 -0
- package/bin/runners/lib/cli-prompts.js +441 -0
- package/bin/runners/lib/cli-scan-cards.js +362 -0
- package/bin/runners/lib/compliance-reporter.js +710 -0
- package/bin/runners/lib/conductor/index.js +671 -0
- package/bin/runners/lib/easy/README.md +123 -0
- package/bin/runners/lib/easy/index.js +140 -0
- package/bin/runners/lib/easy/interactive-wizard.js +788 -0
- package/bin/runners/lib/easy/one-click-firewall.js +564 -0
- package/bin/runners/lib/easy/zero-config-reality.js +714 -0
- package/bin/runners/lib/engines/accessibility-engine.js +218 -18
- package/bin/runners/lib/engines/api-consistency-engine.js +335 -30
- package/bin/runners/lib/engines/async-patterns-engine.js +444 -0
- package/bin/runners/lib/engines/bundle-size-engine.js +433 -0
- package/bin/runners/lib/engines/confidence-scoring.js +276 -0
- package/bin/runners/lib/engines/context-detection.js +264 -0
- package/bin/runners/lib/engines/cross-file-analysis-engine.js +292 -27
- package/bin/runners/lib/engines/database-patterns-engine.js +429 -0
- package/bin/runners/lib/engines/duplicate-code-engine.js +354 -0
- package/bin/runners/lib/engines/empty-catch-engine.js +127 -17
- package/bin/runners/lib/engines/env-variables-engine.js +458 -0
- package/bin/runners/lib/engines/error-handling-engine.js +437 -0
- package/bin/runners/lib/engines/false-positive-prevention.js +630 -0
- package/bin/runners/lib/engines/framework-adapters/index.js +607 -0
- package/bin/runners/lib/engines/framework-detection.js +508 -0
- package/bin/runners/lib/engines/import-order-engine.js +429 -0
- package/bin/runners/lib/engines/mock-data-engine.js +53 -10
- package/bin/runners/lib/engines/naming-conventions-engine.js +544 -0
- package/bin/runners/lib/engines/noise-reduction-engine.js +452 -0
- package/bin/runners/lib/engines/orchestrator.js +334 -0
- package/bin/runners/lib/engines/performance-issues-engine.js +176 -36
- package/bin/runners/lib/engines/react-patterns-engine.js +457 -0
- package/bin/runners/lib/engines/security-vulnerabilities-engine.js +382 -54
- package/bin/runners/lib/engines/type-aware-engine.js +263 -39
- package/bin/runners/lib/engines/vibecheck-engines/index.js +122 -13
- package/bin/runners/lib/engines/vibecheck-engines/lib/ai-hallucination-engine.js +806 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/hardcoded-secrets-engine.js +373 -73
- package/bin/runners/lib/engines/vibecheck-engines/lib/smart-fix-engine.js +577 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/vibe-score-engine.js +543 -0
- package/bin/runners/lib/engines/vibecheck-engines.js +514 -0
- package/bin/runners/lib/enhanced-features/index.js +305 -0
- package/bin/runners/lib/enhanced-output.js +631 -0
- package/bin/runners/lib/enterprise.js +300 -0
- package/bin/runners/lib/entitlements-v2.js +103 -11
- package/bin/runners/lib/firewall/command-validator.js +351 -0
- package/bin/runners/lib/firewall/config.js +341 -0
- package/bin/runners/lib/firewall/content-validator.js +519 -0
- package/bin/runners/lib/firewall/index.js +101 -0
- package/bin/runners/lib/firewall/path-validator.js +256 -0
- package/bin/runners/lib/html-proof-report.js +350 -700
- package/bin/runners/lib/intelligence/cross-repo-intelligence.js +817 -0
- package/bin/runners/lib/mcp-utils.js +425 -0
- package/bin/runners/lib/missions/plan.js +46 -6
- package/bin/runners/lib/missions/templates.js +232 -0
- package/bin/runners/lib/output/index.js +1022 -0
- package/bin/runners/lib/policy-engine.js +652 -0
- package/bin/runners/lib/polish/autofix/accessibility-fixes.js +333 -0
- package/bin/runners/lib/polish/autofix/async-handlers.js +273 -0
- package/bin/runners/lib/polish/autofix/dead-code.js +280 -0
- package/bin/runners/lib/polish/autofix/imports-optimizer.js +344 -0
- package/bin/runners/lib/polish/autofix/index.js +200 -0
- package/bin/runners/lib/polish/autofix/remove-consoles.js +209 -0
- package/bin/runners/lib/polish/autofix/strengthen-types.js +245 -0
- package/bin/runners/lib/polish/backend-checks.js +148 -0
- package/bin/runners/lib/polish/documentation-checks.js +111 -0
- package/bin/runners/lib/polish/frontend-checks.js +168 -0
- package/bin/runners/lib/polish/index.js +71 -0
- package/bin/runners/lib/polish/infrastructure-checks.js +131 -0
- package/bin/runners/lib/polish/library-detection.js +175 -0
- package/bin/runners/lib/polish/performance-checks.js +100 -0
- package/bin/runners/lib/polish/security-checks.js +148 -0
- package/bin/runners/lib/polish/utils.js +203 -0
- package/bin/runners/lib/prompt-builder.js +540 -0
- package/bin/runners/lib/proof-certificate.js +634 -0
- package/bin/runners/lib/reality/accessibility-audit.js +946 -0
- package/bin/runners/lib/reality/api-contract-validator.js +1012 -0
- package/bin/runners/lib/reality/chaos-engineering.js +1084 -0
- package/bin/runners/lib/reality/performance-tracker.js +1077 -0
- package/bin/runners/lib/reality/scenario-generator.js +1404 -0
- package/bin/runners/lib/reality/visual-regression.js +852 -0
- package/bin/runners/lib/reality-profiler.js +717 -0
- package/bin/runners/lib/replay/flight-recorder-viewer.js +1160 -0
- package/bin/runners/lib/review/ai-code-review.js +832 -0
- package/bin/runners/lib/rules/custom-rule-engine.js +985 -0
- package/bin/runners/lib/sbom-generator.js +641 -0
- package/bin/runners/lib/scan-output-enhanced.js +512 -0
- package/bin/runners/lib/scan-output.js +47 -0
- package/bin/runners/lib/security/owasp-scanner.js +939 -0
- package/bin/runners/lib/terminal-ui.js +113 -1
- package/bin/runners/lib/unified-cli-output.js +603 -430
- package/bin/runners/lib/validators/contract-validator.js +283 -0
- package/bin/runners/lib/validators/dead-export-detector.js +279 -0
- package/bin/runners/lib/validators/dep-audit.js +245 -0
- package/bin/runners/lib/validators/env-validator.js +319 -0
- package/bin/runners/lib/validators/index.js +120 -0
- package/bin/runners/lib/validators/license-checker.js +252 -0
- package/bin/runners/lib/validators/route-validator.js +290 -0
- package/bin/runners/runAIAgent.js +5 -10
- package/bin/runners/runAgent.js +3 -0
- package/bin/runners/runApprove.js +1233 -1200
- package/bin/runners/runAuth.js +22 -1
- package/bin/runners/runAuthority.js +528 -0
- package/bin/runners/runCheckpoint.js +4 -24
- package/bin/runners/runClassify.js +862 -859
- package/bin/runners/runConductor.js +772 -0
- package/bin/runners/runContainer.js +366 -0
- package/bin/runners/runContext.js +3 -0
- package/bin/runners/runDoctor.js +28 -41
- package/bin/runners/runEasy.js +410 -0
- package/bin/runners/runFirewall.js +3 -0
- package/bin/runners/runFirewallHook.js +3 -0
- package/bin/runners/runFix.js +76 -66
- package/bin/runners/runGuard.js +411 -18
- package/bin/runners/runIaC.js +372 -0
- package/bin/runners/runInit.js +10 -60
- package/bin/runners/runMcp.js +11 -12
- package/bin/runners/runPolish.js +240 -64
- package/bin/runners/runPromptFirewall.js +5 -12
- package/bin/runners/runProve.js +20 -55
- package/bin/runners/runReality.js +68 -59
- package/bin/runners/runReport.js +31 -5
- package/bin/runners/runRuntime.js +5 -8
- package/bin/runners/runScan.js +194 -1286
- package/bin/runners/runShip.js +695 -47
- package/bin/runners/runTruth.js +3 -0
- package/bin/runners/runValidate.js +7 -11
- package/bin/runners/runVibe.js +791 -0
- package/bin/runners/runWatch.js +14 -23
- package/bin/vibecheck.js +175 -56
- package/mcp-server/index.js +190 -14
- package/mcp-server/package.json +1 -1
- package/mcp-server/tools-v3.js +397 -64
- package/mcp-server/tools.js +495 -0
- package/package.json +1 -1
- package/bin/runners/lib/engines/vibecheck-engines/lib/ast-cache.js +0 -164
- package/bin/runners/lib/engines/vibecheck-engines/lib/code-quality-engine.js +0 -291
- package/bin/runners/lib/engines/vibecheck-engines/lib/console-logs-engine.js +0 -83
- package/bin/runners/lib/engines/vibecheck-engines/lib/dead-code-engine.js +0 -198
- package/bin/runners/lib/engines/vibecheck-engines/lib/deprecated-api-engine.js +0 -275
- package/bin/runners/lib/engines/vibecheck-engines/lib/empty-catch-engine.js +0 -167
- package/bin/runners/lib/engines/vibecheck-engines/lib/file-filter.js +0 -217
- package/bin/runners/lib/engines/vibecheck-engines/lib/mock-data-engine.js +0 -140
- package/bin/runners/lib/engines/vibecheck-engines/lib/parallel-processor.js +0 -164
- package/bin/runners/lib/engines/vibecheck-engines/lib/performance-issues-engine.js +0 -234
- package/bin/runners/lib/engines/vibecheck-engines/lib/type-aware-engine.js +0 -217
- package/bin/runners/lib/engines/vibecheck-engines/lib/unsafe-regex-engine.js +0 -78
- package/mcp-server/index-v1.js +0 -698
|
@@ -0,0 +1,508 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Framework Detection Module
|
|
3
|
+
* Detects frameworks, libraries, and patterns used in the codebase
|
|
4
|
+
* Provides context-aware detection rules for all scanners
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const fs = require("fs");
|
|
8
|
+
const path = require("path");
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Framework types
|
|
12
|
+
*/
|
|
13
|
+
const FRAMEWORKS = {
|
|
14
|
+
NEXTJS: "nextjs",
|
|
15
|
+
NEXTJS_APP_ROUTER: "nextjs-app-router",
|
|
16
|
+
NEXTJS_PAGES_ROUTER: "nextjs-pages-router",
|
|
17
|
+
REACT: "react",
|
|
18
|
+
VUE: "vue",
|
|
19
|
+
SVELTE: "svelte",
|
|
20
|
+
EXPRESS: "express",
|
|
21
|
+
FASTIFY: "fastify",
|
|
22
|
+
NESTJS: "nestjs",
|
|
23
|
+
TRPC: "trpc",
|
|
24
|
+
GRAPHQL: "graphql",
|
|
25
|
+
PRISMA: "prisma",
|
|
26
|
+
DRIZZLE: "drizzle",
|
|
27
|
+
TANSTACK_QUERY: "tanstack-query",
|
|
28
|
+
ZUSTAND: "zustand",
|
|
29
|
+
REDUX: "redux",
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Cached framework detection results
|
|
34
|
+
*/
|
|
35
|
+
let cachedFrameworks = null;
|
|
36
|
+
let cachedProjectRoot = null;
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Detect frameworks from package.json
|
|
40
|
+
*/
|
|
41
|
+
function detectFrameworksFromPackageJson(projectRoot) {
|
|
42
|
+
const packageJsonPath = path.join(projectRoot, "package.json");
|
|
43
|
+
|
|
44
|
+
if (!fs.existsSync(packageJsonPath)) {
|
|
45
|
+
return new Set();
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
try {
|
|
49
|
+
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, "utf-8"));
|
|
50
|
+
const deps = {
|
|
51
|
+
...packageJson.dependencies,
|
|
52
|
+
...packageJson.devDependencies,
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
const frameworks = new Set();
|
|
56
|
+
|
|
57
|
+
// Next.js
|
|
58
|
+
if (deps["next"]) {
|
|
59
|
+
frameworks.add(FRAMEWORKS.NEXTJS);
|
|
60
|
+
// Check for app router vs pages router
|
|
61
|
+
const appDir = path.join(projectRoot, "app");
|
|
62
|
+
const srcAppDir = path.join(projectRoot, "src", "app");
|
|
63
|
+
if (fs.existsSync(appDir) || fs.existsSync(srcAppDir)) {
|
|
64
|
+
frameworks.add(FRAMEWORKS.NEXTJS_APP_ROUTER);
|
|
65
|
+
}
|
|
66
|
+
const pagesDir = path.join(projectRoot, "pages");
|
|
67
|
+
const srcPagesDir = path.join(projectRoot, "src", "pages");
|
|
68
|
+
if (fs.existsSync(pagesDir) || fs.existsSync(srcPagesDir)) {
|
|
69
|
+
frameworks.add(FRAMEWORKS.NEXTJS_PAGES_ROUTER);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// React
|
|
74
|
+
if (deps["react"] || deps["react-dom"]) {
|
|
75
|
+
frameworks.add(FRAMEWORKS.REACT);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// Vue
|
|
79
|
+
if (deps["vue"]) {
|
|
80
|
+
frameworks.add(FRAMEWORKS.VUE);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// Svelte
|
|
84
|
+
if (deps["svelte"]) {
|
|
85
|
+
frameworks.add(FRAMEWORKS.SVELTE);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// Express
|
|
89
|
+
if (deps["express"]) {
|
|
90
|
+
frameworks.add(FRAMEWORKS.EXPRESS);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// Fastify
|
|
94
|
+
if (deps["fastify"]) {
|
|
95
|
+
frameworks.add(FRAMEWORKS.FASTIFY);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// NestJS
|
|
99
|
+
if (deps["@nestjs/core"]) {
|
|
100
|
+
frameworks.add(FRAMEWORKS.NESTJS);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// tRPC
|
|
104
|
+
if (deps["@trpc/server"] || deps["@trpc/client"] || deps["@trpc/react-query"]) {
|
|
105
|
+
frameworks.add(FRAMEWORKS.TRPC);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// GraphQL
|
|
109
|
+
if (deps["graphql"] || deps["@apollo/server"] || deps["@apollo/client"] || deps["graphql-yoga"]) {
|
|
110
|
+
frameworks.add(FRAMEWORKS.GRAPHQL);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// Prisma
|
|
114
|
+
if (deps["@prisma/client"] || deps["prisma"]) {
|
|
115
|
+
frameworks.add(FRAMEWORKS.PRISMA);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// Drizzle
|
|
119
|
+
if (deps["drizzle-orm"]) {
|
|
120
|
+
frameworks.add(FRAMEWORKS.DRIZZLE);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// TanStack Query
|
|
124
|
+
if (deps["@tanstack/react-query"] || deps["react-query"]) {
|
|
125
|
+
frameworks.add(FRAMEWORKS.TANSTACK_QUERY);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// Zustand
|
|
129
|
+
if (deps["zustand"]) {
|
|
130
|
+
frameworks.add(FRAMEWORKS.ZUSTAND);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// Redux
|
|
134
|
+
if (deps["redux"] || deps["@reduxjs/toolkit"]) {
|
|
135
|
+
frameworks.add(FRAMEWORKS.REDUX);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
return frameworks;
|
|
139
|
+
} catch (e) {
|
|
140
|
+
return new Set();
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Get detected frameworks (cached)
|
|
146
|
+
*/
|
|
147
|
+
function getFrameworks(projectRoot) {
|
|
148
|
+
if (cachedFrameworks && cachedProjectRoot === projectRoot) {
|
|
149
|
+
return cachedFrameworks;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
cachedProjectRoot = projectRoot;
|
|
153
|
+
cachedFrameworks = detectFrameworksFromPackageJson(projectRoot);
|
|
154
|
+
return cachedFrameworks;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* Check if a specific framework is used
|
|
159
|
+
*/
|
|
160
|
+
function hasFramework(projectRoot, framework) {
|
|
161
|
+
return getFrameworks(projectRoot).has(framework);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Next.js App Router patterns
|
|
166
|
+
*/
|
|
167
|
+
const NEXTJS_APP_ROUTER_PATTERNS = {
|
|
168
|
+
// Server Components (default in app directory)
|
|
169
|
+
serverComponent: {
|
|
170
|
+
filePatterns: [
|
|
171
|
+
/app\/.*\/page\.(tsx?|jsx?)$/,
|
|
172
|
+
/app\/.*\/layout\.(tsx?|jsx?)$/,
|
|
173
|
+
/app\/.*\/loading\.(tsx?|jsx?)$/,
|
|
174
|
+
/app\/.*\/error\.(tsx?|jsx?)$/,
|
|
175
|
+
/app\/.*\/not-found\.(tsx?|jsx?)$/,
|
|
176
|
+
/app\/.*\/template\.(tsx?|jsx?)$/,
|
|
177
|
+
],
|
|
178
|
+
codePatterns: [
|
|
179
|
+
/^(?!['"]use client['"])/m, // No "use client" directive
|
|
180
|
+
],
|
|
181
|
+
},
|
|
182
|
+
|
|
183
|
+
// Client Components
|
|
184
|
+
clientComponent: {
|
|
185
|
+
codePatterns: [
|
|
186
|
+
/['"]use client['"]/,
|
|
187
|
+
],
|
|
188
|
+
},
|
|
189
|
+
|
|
190
|
+
// Server Actions
|
|
191
|
+
serverAction: {
|
|
192
|
+
codePatterns: [
|
|
193
|
+
/['"]use server['"]/,
|
|
194
|
+
/async\s+function\s+\w+.*formData/i,
|
|
195
|
+
],
|
|
196
|
+
},
|
|
197
|
+
|
|
198
|
+
// Route Handlers
|
|
199
|
+
routeHandler: {
|
|
200
|
+
filePatterns: [
|
|
201
|
+
/app\/.*\/route\.(ts|js)$/,
|
|
202
|
+
/app\/api\/.*\/route\.(ts|js)$/,
|
|
203
|
+
],
|
|
204
|
+
exportPatterns: [
|
|
205
|
+
/export\s+(?:async\s+)?function\s+(?:GET|POST|PUT|DELETE|PATCH|HEAD|OPTIONS)/,
|
|
206
|
+
],
|
|
207
|
+
},
|
|
208
|
+
|
|
209
|
+
// Middleware
|
|
210
|
+
middleware: {
|
|
211
|
+
filePatterns: [
|
|
212
|
+
/middleware\.(ts|js)$/,
|
|
213
|
+
],
|
|
214
|
+
},
|
|
215
|
+
|
|
216
|
+
// Metadata
|
|
217
|
+
metadata: {
|
|
218
|
+
codePatterns: [
|
|
219
|
+
/export\s+(?:const|async\s+function)\s+(?:metadata|generateMetadata)/,
|
|
220
|
+
],
|
|
221
|
+
},
|
|
222
|
+
};
|
|
223
|
+
|
|
224
|
+
/**
|
|
225
|
+
* tRPC patterns
|
|
226
|
+
*/
|
|
227
|
+
const TRPC_PATTERNS = {
|
|
228
|
+
// Router definitions
|
|
229
|
+
router: {
|
|
230
|
+
codePatterns: [
|
|
231
|
+
/\.router\s*\(\s*\{/,
|
|
232
|
+
/createTRPCRouter\s*\(\s*\{/,
|
|
233
|
+
/t\.router\s*\(/,
|
|
234
|
+
],
|
|
235
|
+
},
|
|
236
|
+
|
|
237
|
+
// Procedures
|
|
238
|
+
procedure: {
|
|
239
|
+
codePatterns: [
|
|
240
|
+
/\.query\s*\(/,
|
|
241
|
+
/\.mutation\s*\(/,
|
|
242
|
+
/\.subscription\s*\(/,
|
|
243
|
+
/publicProcedure/,
|
|
244
|
+
/protectedProcedure/,
|
|
245
|
+
],
|
|
246
|
+
},
|
|
247
|
+
|
|
248
|
+
// Context
|
|
249
|
+
context: {
|
|
250
|
+
codePatterns: [
|
|
251
|
+
/createContext/i,
|
|
252
|
+
/createTRPCContext/,
|
|
253
|
+
/ctx\.\w+/,
|
|
254
|
+
],
|
|
255
|
+
},
|
|
256
|
+
|
|
257
|
+
// Client usage
|
|
258
|
+
clientUsage: {
|
|
259
|
+
codePatterns: [
|
|
260
|
+
/trpc\.\w+\.useQuery/,
|
|
261
|
+
/trpc\.\w+\.useMutation/,
|
|
262
|
+
/api\.\w+\.useQuery/,
|
|
263
|
+
/api\.\w+\.useMutation/,
|
|
264
|
+
],
|
|
265
|
+
},
|
|
266
|
+
};
|
|
267
|
+
|
|
268
|
+
/**
|
|
269
|
+
* React Server Components patterns
|
|
270
|
+
*/
|
|
271
|
+
const RSC_PATTERNS = {
|
|
272
|
+
// Async components (RSC feature)
|
|
273
|
+
asyncComponent: {
|
|
274
|
+
codePatterns: [
|
|
275
|
+
/export\s+(?:default\s+)?async\s+function\s+\w+.*\{/,
|
|
276
|
+
/async\s+function\s+\w+Component/,
|
|
277
|
+
],
|
|
278
|
+
},
|
|
279
|
+
|
|
280
|
+
// Server-only imports
|
|
281
|
+
serverOnlyImports: {
|
|
282
|
+
codePatterns: [
|
|
283
|
+
/import\s+.*from\s+['"]server-only['"]/,
|
|
284
|
+
/import\s+['"]server-only['"]/,
|
|
285
|
+
],
|
|
286
|
+
},
|
|
287
|
+
|
|
288
|
+
// Client-only imports
|
|
289
|
+
clientOnlyImports: {
|
|
290
|
+
codePatterns: [
|
|
291
|
+
/import\s+.*from\s+['"]client-only['"]/,
|
|
292
|
+
],
|
|
293
|
+
},
|
|
294
|
+
};
|
|
295
|
+
|
|
296
|
+
/**
|
|
297
|
+
* GraphQL patterns
|
|
298
|
+
*/
|
|
299
|
+
const GRAPHQL_PATTERNS = {
|
|
300
|
+
// Schema definitions
|
|
301
|
+
schema: {
|
|
302
|
+
codePatterns: [
|
|
303
|
+
/gql`/,
|
|
304
|
+
/graphql`/,
|
|
305
|
+
/type\s+Query\s*\{/,
|
|
306
|
+
/type\s+Mutation\s*\{/,
|
|
307
|
+
/type\s+Subscription\s*\{/,
|
|
308
|
+
],
|
|
309
|
+
},
|
|
310
|
+
|
|
311
|
+
// Resolvers
|
|
312
|
+
resolvers: {
|
|
313
|
+
codePatterns: [
|
|
314
|
+
/resolvers\s*[=:]\s*\{/,
|
|
315
|
+
/Query\s*:\s*\{/,
|
|
316
|
+
/Mutation\s*:\s*\{/,
|
|
317
|
+
],
|
|
318
|
+
},
|
|
319
|
+
|
|
320
|
+
// Hooks
|
|
321
|
+
hooks: {
|
|
322
|
+
codePatterns: [
|
|
323
|
+
/useQuery\s*\(/,
|
|
324
|
+
/useMutation\s*\(/,
|
|
325
|
+
/useSubscription\s*\(/,
|
|
326
|
+
/useLazyQuery\s*\(/,
|
|
327
|
+
],
|
|
328
|
+
},
|
|
329
|
+
};
|
|
330
|
+
|
|
331
|
+
/**
|
|
332
|
+
* Check if file is a Next.js App Router file
|
|
333
|
+
*/
|
|
334
|
+
function isNextjsAppRouterFile(filePath) {
|
|
335
|
+
const normalizedPath = filePath.replace(/\\/g, "/");
|
|
336
|
+
return NEXTJS_APP_ROUTER_PATTERNS.serverComponent.filePatterns.some(p => p.test(normalizedPath)) ||
|
|
337
|
+
NEXTJS_APP_ROUTER_PATTERNS.routeHandler.filePatterns.some(p => p.test(normalizedPath));
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
/**
|
|
341
|
+
* Check if file is a server component (no "use client")
|
|
342
|
+
*/
|
|
343
|
+
function isServerComponent(code, filePath) {
|
|
344
|
+
const normalizedPath = filePath.replace(/\\/g, "/");
|
|
345
|
+
|
|
346
|
+
// Check if it's in app directory
|
|
347
|
+
if (!normalizedPath.includes("/app/")) {
|
|
348
|
+
return false;
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
// Check for "use client" directive
|
|
352
|
+
if (/['"]use client['"]/.test(code)) {
|
|
353
|
+
return false;
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
return true;
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
/**
|
|
360
|
+
* Check if file is a client component
|
|
361
|
+
*/
|
|
362
|
+
function isClientComponent(code) {
|
|
363
|
+
return /['"]use client['"]/.test(code);
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
/**
|
|
367
|
+
* Check if file contains server actions
|
|
368
|
+
*/
|
|
369
|
+
function hasServerActions(code) {
|
|
370
|
+
return /['"]use server['"]/.test(code);
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
/**
|
|
374
|
+
* Check if file is a route handler
|
|
375
|
+
*/
|
|
376
|
+
function isRouteHandler(filePath, code) {
|
|
377
|
+
const normalizedPath = filePath.replace(/\\/g, "/");
|
|
378
|
+
|
|
379
|
+
if (!NEXTJS_APP_ROUTER_PATTERNS.routeHandler.filePatterns.some(p => p.test(normalizedPath))) {
|
|
380
|
+
return false;
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
return NEXTJS_APP_ROUTER_PATTERNS.routeHandler.exportPatterns.some(p => p.test(code));
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
/**
|
|
387
|
+
* Check if code uses tRPC
|
|
388
|
+
*/
|
|
389
|
+
function usesTRPC(code) {
|
|
390
|
+
return Object.values(TRPC_PATTERNS).some(category =>
|
|
391
|
+
category.codePatterns.some(p => p.test(code))
|
|
392
|
+
);
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
/**
|
|
396
|
+
* Check if code uses GraphQL
|
|
397
|
+
*/
|
|
398
|
+
function usesGraphQL(code) {
|
|
399
|
+
return Object.values(GRAPHQL_PATTERNS).some(category =>
|
|
400
|
+
category.codePatterns.some(p => p.test(code))
|
|
401
|
+
);
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
/**
|
|
405
|
+
* Get file context based on framework patterns
|
|
406
|
+
*/
|
|
407
|
+
function getFileContext(filePath, code, projectRoot) {
|
|
408
|
+
const context = {
|
|
409
|
+
frameworks: Array.from(getFrameworks(projectRoot)),
|
|
410
|
+
isServerComponent: false,
|
|
411
|
+
isClientComponent: false,
|
|
412
|
+
isRouteHandler: false,
|
|
413
|
+
hasServerActions: false,
|
|
414
|
+
usesTRPC: false,
|
|
415
|
+
usesGraphQL: false,
|
|
416
|
+
isAppRouterFile: false,
|
|
417
|
+
isAPIRoute: false,
|
|
418
|
+
isMiddleware: false,
|
|
419
|
+
};
|
|
420
|
+
|
|
421
|
+
const normalizedPath = filePath.replace(/\\/g, "/");
|
|
422
|
+
|
|
423
|
+
// Next.js specific
|
|
424
|
+
if (hasFramework(projectRoot, FRAMEWORKS.NEXTJS)) {
|
|
425
|
+
context.isAppRouterFile = isNextjsAppRouterFile(filePath);
|
|
426
|
+
context.isServerComponent = isServerComponent(code, filePath);
|
|
427
|
+
context.isClientComponent = isClientComponent(code);
|
|
428
|
+
context.isRouteHandler = isRouteHandler(filePath, code);
|
|
429
|
+
context.hasServerActions = hasServerActions(code);
|
|
430
|
+
context.isAPIRoute = /\/api\//.test(normalizedPath);
|
|
431
|
+
context.isMiddleware = /middleware\.(ts|js)$/.test(normalizedPath);
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
// tRPC
|
|
435
|
+
context.usesTRPC = usesTRPC(code);
|
|
436
|
+
|
|
437
|
+
// GraphQL
|
|
438
|
+
context.usesGraphQL = usesGraphQL(code);
|
|
439
|
+
|
|
440
|
+
return context;
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
/**
|
|
444
|
+
* Framework-specific rules for scanners
|
|
445
|
+
*/
|
|
446
|
+
const FRAMEWORK_RULES = {
|
|
447
|
+
// Next.js App Router specific rules
|
|
448
|
+
nextjsAppRouter: {
|
|
449
|
+
// Server Components can use async/await directly
|
|
450
|
+
allowAsyncComponents: true,
|
|
451
|
+
// Server Components can access server-only resources
|
|
452
|
+
allowServerOnlyImports: true,
|
|
453
|
+
// Route handlers have specific patterns
|
|
454
|
+
routeHandlerPatterns: ["GET", "POST", "PUT", "DELETE", "PATCH"],
|
|
455
|
+
},
|
|
456
|
+
|
|
457
|
+
// tRPC specific rules
|
|
458
|
+
trpc: {
|
|
459
|
+
// tRPC procedures are type-safe by design
|
|
460
|
+
skipSQLInjectionInProcedures: true,
|
|
461
|
+
// Input validation is handled by zod
|
|
462
|
+
hasInputValidation: true,
|
|
463
|
+
},
|
|
464
|
+
|
|
465
|
+
// GraphQL specific rules
|
|
466
|
+
graphql: {
|
|
467
|
+
// Resolvers have specific patterns
|
|
468
|
+
resolverPatterns: ["Query", "Mutation", "Subscription"],
|
|
469
|
+
// Variables are parameterized by design
|
|
470
|
+
skipSQLInjectionInResolvers: true,
|
|
471
|
+
},
|
|
472
|
+
|
|
473
|
+
// Prisma specific rules
|
|
474
|
+
prisma: {
|
|
475
|
+
// Prisma queries are parameterized
|
|
476
|
+
skipSQLInjectionForPrisma: true,
|
|
477
|
+
// Common patterns
|
|
478
|
+
queryPatterns: ["findUnique", "findFirst", "findMany", "create", "update", "delete"],
|
|
479
|
+
},
|
|
480
|
+
};
|
|
481
|
+
|
|
482
|
+
/**
|
|
483
|
+
* Clear the framework cache (useful for testing or when package.json changes)
|
|
484
|
+
*/
|
|
485
|
+
function clearCache() {
|
|
486
|
+
cachedFrameworks = null;
|
|
487
|
+
cachedProjectRoot = null;
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
module.exports = {
|
|
491
|
+
FRAMEWORKS,
|
|
492
|
+
getFrameworks,
|
|
493
|
+
hasFramework,
|
|
494
|
+
getFileContext,
|
|
495
|
+
isNextjsAppRouterFile,
|
|
496
|
+
isServerComponent,
|
|
497
|
+
isClientComponent,
|
|
498
|
+
isRouteHandler,
|
|
499
|
+
hasServerActions,
|
|
500
|
+
usesTRPC,
|
|
501
|
+
usesGraphQL,
|
|
502
|
+
NEXTJS_APP_ROUTER_PATTERNS,
|
|
503
|
+
TRPC_PATTERNS,
|
|
504
|
+
RSC_PATTERNS,
|
|
505
|
+
GRAPHQL_PATTERNS,
|
|
506
|
+
FRAMEWORK_RULES,
|
|
507
|
+
clearCache,
|
|
508
|
+
};
|