@soulbatical/tetra-dev-toolkit 1.20.26 → 1.21.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/tetra-init-smoke.js
CHANGED
|
File without changes
|
|
@@ -33,46 +33,46 @@ export async function run(config, projectRoot) {
|
|
|
33
33
|
}
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
-
//
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
files = [...new Set(files)]
|
|
36
|
+
// Discover ALL backend source files (no path conventions assumed).
|
|
37
|
+
// Strategy: scan every .ts/.js file and detect Express route handlers by content.
|
|
38
|
+
// This catches feature folders, custom layouts, monorepo backends, etc.
|
|
39
|
+
const candidates = await glob('**/*.{ts,js,mts,cts,mjs,cjs}', {
|
|
40
|
+
cwd: projectRoot,
|
|
41
|
+
ignore: [
|
|
42
|
+
...(config.ignore || []),
|
|
43
|
+
'node_modules/**',
|
|
44
|
+
'**/node_modules/**',
|
|
45
|
+
'dist/**',
|
|
46
|
+
'**/dist/**',
|
|
47
|
+
'build/**',
|
|
48
|
+
'**/build/**',
|
|
49
|
+
'.next/**',
|
|
50
|
+
'**/.next/**',
|
|
51
|
+
'coverage/**',
|
|
52
|
+
'**/coverage/**',
|
|
53
|
+
'**/*.test.*',
|
|
54
|
+
'**/*.spec.*',
|
|
55
|
+
'**/*.d.ts',
|
|
56
|
+
'**/*.js.map',
|
|
57
|
+
// Frontend folders – these are not Express backends
|
|
58
|
+
'frontend/**',
|
|
59
|
+
'web/**',
|
|
60
|
+
'app/**',
|
|
61
|
+
'pages/**',
|
|
62
|
+
'src/app/**',
|
|
63
|
+
'src/pages/**'
|
|
64
|
+
]
|
|
65
|
+
})
|
|
66
|
+
|
|
67
|
+
const files = [...new Set(candidates)]
|
|
69
68
|
|
|
70
69
|
if (files.length === 0) {
|
|
71
70
|
results.skipped = true
|
|
72
|
-
results.skipReason = 'No
|
|
71
|
+
results.skipReason = 'No source files found to scan'
|
|
73
72
|
return results
|
|
74
73
|
}
|
|
75
74
|
|
|
75
|
+
let backendFilesScanned = 0
|
|
76
76
|
for (const file of files) {
|
|
77
77
|
const filePath = `${projectRoot}/${file}`
|
|
78
78
|
let content
|
|
@@ -82,10 +82,21 @@ export async function run(config, projectRoot) {
|
|
|
82
82
|
continue
|
|
83
83
|
}
|
|
84
84
|
|
|
85
|
+
if (!isExpressRouteFile(content)) continue
|
|
86
|
+
|
|
87
|
+
backendFilesScanned++
|
|
85
88
|
const lines = content.split('\n')
|
|
86
89
|
analyzeFile(file, lines, results)
|
|
87
90
|
}
|
|
88
91
|
|
|
92
|
+
results.info.backendFilesScanned = backendFilesScanned
|
|
93
|
+
|
|
94
|
+
if (backendFilesScanned === 0) {
|
|
95
|
+
results.skipped = true
|
|
96
|
+
results.skipReason = 'No Express route handlers detected in scanned files'
|
|
97
|
+
return results
|
|
98
|
+
}
|
|
99
|
+
|
|
89
100
|
results.passed = results.findings.filter(f => f.severity === 'critical' || f.severity === 'high').length === 0
|
|
90
101
|
results.info.violations = results.findings.length
|
|
91
102
|
results.info.compliant = results.info.totalEndpoints - results.info.violations
|
|
@@ -93,6 +104,30 @@ export async function run(config, projectRoot) {
|
|
|
93
104
|
return results
|
|
94
105
|
}
|
|
95
106
|
|
|
107
|
+
/**
|
|
108
|
+
* Heuristic: does this file contain Express-style route handlers that
|
|
109
|
+
* eventually call res.json() or res.status().json()?
|
|
110
|
+
*
|
|
111
|
+
* We require BOTH:
|
|
112
|
+
* 1. An indicator that this is server code (express import / Request type / router/app verb)
|
|
113
|
+
* 2. At least one res.json() / res.status(...).json() call
|
|
114
|
+
*
|
|
115
|
+
* This avoids scanning frontend files that happen to use the variable name `res`.
|
|
116
|
+
*/
|
|
117
|
+
function isExpressRouteFile(content) {
|
|
118
|
+
const hasResJsonCall = /\bres\s*(?:\.\s*status\s*\([^)]*\)\s*)?\.\s*json\s*\(/.test(content)
|
|
119
|
+
if (!hasResJsonCall) return false
|
|
120
|
+
|
|
121
|
+
const looksLikeExpress =
|
|
122
|
+
/from\s+['"]express['"]/.test(content) ||
|
|
123
|
+
/require\s*\(\s*['"]express['"]\s*\)/.test(content) ||
|
|
124
|
+
/\b(?:Request|Response|NextFunction|Router)\b/.test(content) ||
|
|
125
|
+
/\b(?:router|app)\s*\.\s*(?:get|post|put|patch|delete|all|use)\s*\(/.test(content) ||
|
|
126
|
+
/\bexpress\s*\(\s*\)/.test(content)
|
|
127
|
+
|
|
128
|
+
return looksLikeExpress
|
|
129
|
+
}
|
|
130
|
+
|
|
96
131
|
function analyzeFile(file, lines, results) {
|
|
97
132
|
for (let i = 0; i < lines.length; i++) {
|
|
98
133
|
const line = lines[i]
|