api-tests-coverage 1.0.15 → 1.0.17
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/dist/dashboard/dist/assets/_basePickBy-C2jmWITn.js +1 -0
- package/dist/dashboard/dist/assets/_baseUniq-DE6cyzJb.js +1 -0
- package/dist/dashboard/dist/assets/arc-B-Q4nGPT.js +1 -0
- package/dist/dashboard/dist/assets/architectureDiagram-VXUJARFQ-C_5dqWCI.js +36 -0
- package/dist/dashboard/dist/assets/blockDiagram-VD42YOAC-DbGIO6Kt.js +122 -0
- package/dist/dashboard/dist/assets/c4Diagram-YG6GDRKO-CAFpcejP.js +10 -0
- package/dist/dashboard/dist/assets/channel-Di9el3wE.js +1 -0
- package/dist/dashboard/dist/assets/chunk-4BX2VUAB-DY1boKsq.js +1 -0
- package/dist/dashboard/dist/assets/chunk-55IACEB6-BSL35gyW.js +1 -0
- package/dist/dashboard/dist/assets/chunk-B4BG7PRW-eTDXrKrv.js +165 -0
- package/dist/dashboard/dist/assets/chunk-DI55MBZ5-M-8I3jEy.js +220 -0
- package/dist/dashboard/dist/assets/chunk-FMBD7UC4-bSA0XiS0.js +15 -0
- package/dist/dashboard/dist/assets/chunk-QN33PNHL-BrOIYUBs.js +1 -0
- package/dist/dashboard/dist/assets/chunk-QZHKN3VN-CliaQGD4.js +1 -0
- package/dist/dashboard/dist/assets/chunk-TZMSLE5B-CyhcxGB1.js +1 -0
- package/dist/dashboard/dist/assets/classDiagram-2ON5EDUG-BkGN4Cpz.js +1 -0
- package/dist/dashboard/dist/assets/classDiagram-v2-WZHVMYZB-BkGN4Cpz.js +1 -0
- package/dist/dashboard/dist/assets/clone-Cvq8JuOb.js +1 -0
- package/dist/dashboard/dist/assets/cose-bilkent-S5V4N54A-BUkL7Wtq.js +1 -0
- package/dist/dashboard/dist/assets/dagre-6UL2VRFP-B8oEROJc.js +4 -0
- package/dist/dashboard/dist/assets/diagram-PSM6KHXK-5uki9Dw8.js +24 -0
- package/dist/dashboard/dist/assets/diagram-QEK2KX5R-BRNhmby2.js +43 -0
- package/dist/dashboard/dist/assets/diagram-S2PKOQOG-D-ku_X8U.js +24 -0
- package/dist/dashboard/dist/assets/erDiagram-Q2GNP2WA-DGl6gPe2.js +60 -0
- package/dist/dashboard/dist/assets/flowDiagram-NV44I4VS-Co89qYBD.js +162 -0
- package/dist/dashboard/dist/assets/ganttDiagram-JELNMOA3-2r3WpWQC.js +267 -0
- package/dist/dashboard/dist/assets/gitGraphDiagram-V2S2FVAM-CuJ5l3TK.js +65 -0
- package/dist/dashboard/dist/assets/graph-ZtgwAPQj.js +1 -0
- package/dist/dashboard/dist/assets/index-D3sRJga7.js +777 -0
- package/dist/dashboard/dist/assets/infoDiagram-HS3SLOUP-ujnMqVz3.js +2 -0
- package/dist/dashboard/dist/assets/journeyDiagram-XKPGCS4Q-DQzfeBIo.js +139 -0
- package/dist/dashboard/dist/assets/kanban-definition-3W4ZIXB7-ueIaoeks.js +89 -0
- package/dist/dashboard/dist/assets/layout-B1fTYUMj.js +1 -0
- package/dist/dashboard/dist/assets/mindmap-definition-VGOIOE7T-B7wYeLe1.js +68 -0
- package/dist/dashboard/dist/assets/pieDiagram-ADFJNKIX-Bf8vKEOf.js +30 -0
- package/dist/dashboard/dist/assets/quadrantDiagram-AYHSOK5B-CM8qiFLR.js +7 -0
- package/dist/dashboard/dist/assets/requirementDiagram-UZGBJVZJ-DPTtP4Ve.js +64 -0
- package/dist/dashboard/dist/assets/sankeyDiagram-TZEHDZUN-DEVTdH0h.js +10 -0
- package/dist/dashboard/dist/assets/sequenceDiagram-WL72ISMW-Bjr5wgXg.js +145 -0
- package/dist/dashboard/dist/assets/stateDiagram-FKZM4ZOC-DDrhZYly.js +1 -0
- package/dist/dashboard/dist/assets/stateDiagram-v2-4FDKWEC3-Im6pH8C-.js +1 -0
- package/dist/dashboard/dist/assets/timeline-definition-IT6M3QCI-DAT3r9va.js +61 -0
- package/dist/dashboard/dist/assets/treemap-GDKQZRPO-BlA8rg0m.js +162 -0
- package/dist/dashboard/dist/assets/xychartDiagram-PRI3JC2R-7aSkQtVu.js +7 -0
- package/dist/src/ast/astTypes.d.ts +86 -0
- package/dist/src/ast/astTypes.d.ts.map +1 -1
- package/dist/src/discovery/fileClassifier.d.ts.map +1 -1
- package/dist/src/discovery/fileClassifier.js +15 -16
- package/dist/src/discovery/frameworkDetector.d.ts +28 -0
- package/dist/src/discovery/frameworkDetector.d.ts.map +1 -0
- package/dist/src/discovery/frameworkDetector.js +189 -0
- package/dist/src/discovery/projectDiscovery.d.ts +5 -1
- package/dist/src/discovery/projectDiscovery.d.ts.map +1 -1
- package/dist/src/discovery/projectDiscovery.js +8 -1
- package/dist/src/inference/routeInference.d.ts.map +1 -1
- package/dist/src/inference/routeInference.js +224 -1
- package/dist/src/languages/java/graphqlSchemaParser.d.ts +65 -0
- package/dist/src/languages/java/graphqlSchemaParser.d.ts.map +1 -0
- package/dist/src/languages/java/graphqlSchemaParser.js +164 -0
- package/dist/src/languages/java/mybatisXmlParser.d.ts +52 -0
- package/dist/src/languages/java/mybatisXmlParser.d.ts.map +1 -0
- package/dist/src/languages/java/mybatisXmlParser.js +107 -0
- package/dist/src/languages/java/semanticBuilder.d.ts.map +1 -1
- package/dist/src/languages/java/semanticBuilder.js +69 -12
- package/dist/src/languages/javascript/angularDetector.d.ts +74 -0
- package/dist/src/languages/javascript/angularDetector.d.ts.map +1 -0
- package/dist/src/languages/javascript/angularDetector.js +227 -0
- package/dist/src/languages/javascript/assertionResolver.js +6 -4
- package/dist/src/languages/javascript/hapiDetector.d.ts +40 -0
- package/dist/src/languages/javascript/hapiDetector.d.ts.map +1 -0
- package/dist/src/languages/javascript/hapiDetector.js +174 -0
- package/dist/src/languages/javascript/mongooseDetector.d.ts +65 -0
- package/dist/src/languages/javascript/mongooseDetector.d.ts.map +1 -0
- package/dist/src/languages/javascript/mongooseDetector.js +237 -0
- package/dist/src/languages/javascript/vueDetector.d.ts +42 -0
- package/dist/src/languages/javascript/vueDetector.d.ts.map +1 -0
- package/dist/src/languages/javascript/vueDetector.js +109 -0
- package/dist/src/languages/python/index.d.ts +6 -2
- package/dist/src/languages/python/index.d.ts.map +1 -1
- package/dist/src/languages/python/index.js +200 -5
- package/dist/src/languages/python/testPatternDetector.d.ts +70 -0
- package/dist/src/languages/python/testPatternDetector.d.ts.map +1 -0
- package/dist/src/languages/python/testPatternDetector.js +201 -0
- package/dist/src/pipeline/confidence.d.ts +6 -1
- package/dist/src/pipeline/confidence.d.ts.map +1 -1
- package/dist/src/pipeline/confidence.js +8 -3
- package/dist/src/pipeline/graph.d.ts.map +1 -1
- package/dist/src/pipeline/graph.js +16 -4
- package/dist/src/pipeline/stages/ast/astStage.d.ts.map +1 -1
- package/dist/src/pipeline/stages/ast/astStage.js +51 -1
- package/dist/src/pipeline/stages/ast/baseUrlComposer.d.ts +44 -0
- package/dist/src/pipeline/stages/ast/baseUrlComposer.d.ts.map +1 -0
- package/dist/src/pipeline/stages/ast/baseUrlComposer.js +97 -0
- package/dist/src/pipeline/stages/ast/crossFileResolutionPass.d.ts +54 -0
- package/dist/src/pipeline/stages/ast/crossFileResolutionPass.d.ts.map +1 -0
- package/dist/src/pipeline/stages/ast/crossFileResolutionPass.js +88 -0
- package/dist/src/pipeline/stages/ast/crossFileResolver.d.ts.map +1 -1
- package/dist/src/pipeline/stages/ast/crossFileResolver.js +39 -1
- package/dist/src/pipeline/stages/ast/graphBuilder.d.ts.map +1 -1
- package/dist/src/pipeline/stages/ast/graphBuilder.js +81 -0
- package/dist/src/pipeline/stages/ast/optionalAuthUnifier.d.ts +41 -0
- package/dist/src/pipeline/stages/ast/optionalAuthUnifier.d.ts.map +1 -0
- package/dist/src/pipeline/stages/ast/optionalAuthUnifier.js +101 -0
- package/dist/src/pipeline/stages/ast/resolvers/angularInjectionResolver.d.ts +18 -0
- package/dist/src/pipeline/stages/ast/resolvers/angularInjectionResolver.d.ts.map +1 -0
- package/dist/src/pipeline/stages/ast/resolvers/angularInjectionResolver.js +96 -0
- package/dist/src/pipeline/stages/ast/resolvers/dddLayerResolver.d.ts +46 -0
- package/dist/src/pipeline/stages/ast/resolvers/dddLayerResolver.d.ts.map +1 -0
- package/dist/src/pipeline/stages/ast/resolvers/dddLayerResolver.js +314 -0
- package/dist/src/pipeline/stages/ast/resolvers/expressRouterResolver.d.ts +17 -0
- package/dist/src/pipeline/stages/ast/resolvers/expressRouterResolver.d.ts.map +1 -0
- package/dist/src/pipeline/stages/ast/resolvers/expressRouterResolver.js +65 -0
- package/dist/src/pipeline/stages/ast/resolvers/flaskBlueprintResolver.d.ts +17 -0
- package/dist/src/pipeline/stages/ast/resolvers/flaskBlueprintResolver.d.ts.map +1 -0
- package/dist/src/pipeline/stages/ast/resolvers/flaskBlueprintResolver.js +114 -0
- package/dist/src/pipeline/stages/ast/resolvers/mybatisResolver.d.ts +27 -0
- package/dist/src/pipeline/stages/ast/resolvers/mybatisResolver.d.ts.map +1 -0
- package/dist/src/pipeline/stages/ast/resolvers/mybatisResolver.js +130 -0
- package/dist/src/pipeline/stages/ast/resolvers/vuexActionResolver.d.ts +17 -0
- package/dist/src/pipeline/stages/ast/resolvers/vuexActionResolver.d.ts.map +1 -0
- package/dist/src/pipeline/stages/ast/resolvers/vuexActionResolver.js +80 -0
- package/dist/src/pipeline/stages/ast/rulesEnforcer.d.ts +24 -0
- package/dist/src/pipeline/stages/ast/rulesEnforcer.d.ts.map +1 -0
- package/dist/src/pipeline/stages/ast/rulesEnforcer.js +411 -0
- package/dist/src/pipeline/stages/ast/types.d.ts +114 -1
- package/dist/src/pipeline/stages/ast/types.d.ts.map +1 -1
- package/dist/src/pipeline/stages/merge/conflictDetector.d.ts +2 -0
- package/dist/src/pipeline/stages/merge/conflictDetector.d.ts.map +1 -1
- package/dist/src/pipeline/stages/merge/conflictDetector.js +54 -2
- package/dist/src/pipeline/stages/merge/coverageMappingBuilder.d.ts.map +1 -1
- package/dist/src/pipeline/stages/merge/coverageMappingBuilder.js +67 -3
- package/dist/src/pipeline/stages/tia/mockBoundaryDetector.d.ts.map +1 -1
- package/dist/src/pipeline/stages/tia/mockBoundaryDetector.js +8 -1
- package/dist/src/pipeline/stages/tia/parameterizedTestExpander.js +8 -4
- package/dist/src/pipeline/stages/tia/testLayerClassifier.d.ts.map +1 -1
- package/dist/src/pipeline/stages/tia/testLayerClassifier.js +41 -10
- package/dist/src/pipeline/types.d.ts +1 -1
- package/dist/src/pipeline/types.d.ts.map +1 -1
- package/package.json +3 -3
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* HapiJS pattern detector (Feature 27, Sub-PR 8)
|
|
4
|
+
*
|
|
5
|
+
* Detects:
|
|
6
|
+
* 1. server.route({ method, path, options: { auth, validate, handler } })
|
|
7
|
+
* 2. Joi validator chains: Joi.string().required(), Joi.number().min().max().default()
|
|
8
|
+
* 3. auth: 'jwt' = required, auth: { mode: 'try' } = optional
|
|
9
|
+
* 4. Boom error responses: Boom.notFound(), Boom.unauthorized()
|
|
10
|
+
*/
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.detectHapiRoutes = detectHapiRoutes;
|
|
13
|
+
exports.detectBoomErrors = detectBoomErrors;
|
|
14
|
+
/** Map Boom methods to HTTP status codes */
|
|
15
|
+
const BOOM_STATUS_MAP = {
|
|
16
|
+
badRequest: 400,
|
|
17
|
+
unauthorized: 401,
|
|
18
|
+
forbidden: 403,
|
|
19
|
+
notFound: 404,
|
|
20
|
+
conflict: 409,
|
|
21
|
+
badData: 422,
|
|
22
|
+
internal: 500,
|
|
23
|
+
badImplementation: 500,
|
|
24
|
+
notImplemented: 501,
|
|
25
|
+
badGateway: 502,
|
|
26
|
+
serverUnavailable: 503,
|
|
27
|
+
gatewayTimeout: 504,
|
|
28
|
+
};
|
|
29
|
+
/**
|
|
30
|
+
* Detect HapiJS route definitions from source text.
|
|
31
|
+
*/
|
|
32
|
+
function detectHapiRoutes(sourceText, filePath) {
|
|
33
|
+
var _a, _b, _c, _d;
|
|
34
|
+
const routes = [];
|
|
35
|
+
const lines = sourceText.split('\n');
|
|
36
|
+
for (let i = 0; i < lines.length; i++) {
|
|
37
|
+
const line = lines[i];
|
|
38
|
+
// Look for method: 'GET' and path: '/articles' patterns close together
|
|
39
|
+
const methodMatch = line.match(/method\s*:\s*['"](\w+)['"]/);
|
|
40
|
+
if (!methodMatch)
|
|
41
|
+
continue;
|
|
42
|
+
const method = methodMatch[1].toUpperCase();
|
|
43
|
+
// Find path in nearby lines (within 5 lines)
|
|
44
|
+
let path = '';
|
|
45
|
+
let auth;
|
|
46
|
+
let validation;
|
|
47
|
+
for (let j = Math.max(0, i - 3); j < Math.min(i + 10, lines.length); j++) {
|
|
48
|
+
const nearLine = lines[j];
|
|
49
|
+
// path: '/articles/{slug}'
|
|
50
|
+
const pathMatch = nearLine.match(/path\s*:\s*['"]([^'"]+)['"]/);
|
|
51
|
+
if (pathMatch)
|
|
52
|
+
path = pathMatch[1];
|
|
53
|
+
// auth: 'jwt' or auth: 'simple'
|
|
54
|
+
const authSimple = nearLine.match(/auth\s*:\s*['"](\w+)['"]/);
|
|
55
|
+
if (authSimple) {
|
|
56
|
+
auth = { strategy: authSimple[1], mode: 'required' };
|
|
57
|
+
}
|
|
58
|
+
// auth: { mode: 'try' } or auth: { mode: 'optional' } — single-line case
|
|
59
|
+
const authMode = nearLine.match(/(?:auth|mode)\s*:\s*[{]?\s*mode\s*:\s*['"](\w+)['"]/);
|
|
60
|
+
if (authMode) {
|
|
61
|
+
auth = {
|
|
62
|
+
strategy: auth === null || auth === void 0 ? void 0 : auth.strategy,
|
|
63
|
+
mode: authMode[1] === 'try' || authMode[1] === 'optional' ? 'optional' : 'required',
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
else if (/auth\s*:\s*\{/.test(nearLine) || /auth\s*\{/.test(nearLine)) {
|
|
67
|
+
// Multi-line auth object: scan the next 5 lines for mode: 'try' / 'optional'
|
|
68
|
+
for (let m = j + 1; m < Math.min(j + 6, lines.length); m++) {
|
|
69
|
+
const modeMatch = lines[m].match(/mode\s*:\s*['"](\w+)['"]/);
|
|
70
|
+
if (modeMatch) {
|
|
71
|
+
auth = {
|
|
72
|
+
strategy: auth === null || auth === void 0 ? void 0 : auth.strategy,
|
|
73
|
+
mode: modeMatch[1] === 'try' || modeMatch[1] === 'optional' ? 'optional' : 'required',
|
|
74
|
+
};
|
|
75
|
+
break;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
// auth: false
|
|
80
|
+
if (/auth\s*:\s*false/.test(nearLine)) {
|
|
81
|
+
auth = undefined; // Public route
|
|
82
|
+
}
|
|
83
|
+
// validate.query or validate.payload with Joi
|
|
84
|
+
if (/validate\s*:/.test(nearLine)) {
|
|
85
|
+
const queryParams = [];
|
|
86
|
+
const payloadParams = [];
|
|
87
|
+
// Scan validation block
|
|
88
|
+
for (let k = j; k < Math.min(j + 15, lines.length); k++) {
|
|
89
|
+
const valLine = lines[k];
|
|
90
|
+
// query: { ... } — extract Joi fields from same line and subsequent lines
|
|
91
|
+
if (/query\s*:/.test(valLine)) {
|
|
92
|
+
// Same-line extraction
|
|
93
|
+
const paramMatch = valLine.match(/(\w+)\s*:\s*Joi\./g);
|
|
94
|
+
if (paramMatch) {
|
|
95
|
+
for (const pm of paramMatch) {
|
|
96
|
+
const name = (_a = pm.match(/(\w+)\s*:/)) === null || _a === void 0 ? void 0 : _a[1];
|
|
97
|
+
if (name)
|
|
98
|
+
queryParams.push(name);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
// Multi-line extraction: scan subsequent lines for fieldName: Joi. patterns
|
|
102
|
+
for (let q = k + 1; q < Math.min(k + 16, lines.length); q++) {
|
|
103
|
+
const subLine = lines[q];
|
|
104
|
+
if (/}\s*[),]/.test(subLine) || /]\s*,/.test(subLine))
|
|
105
|
+
break;
|
|
106
|
+
const fieldMatch = subLine.match(/(\w+)\s*:\s*Joi\./g);
|
|
107
|
+
if (fieldMatch) {
|
|
108
|
+
for (const fm of fieldMatch) {
|
|
109
|
+
const name = (_b = fm.match(/(\w+)\s*:/)) === null || _b === void 0 ? void 0 : _b[1];
|
|
110
|
+
if (name && !queryParams.includes(name))
|
|
111
|
+
queryParams.push(name);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
// payload: { ... } — extract Joi fields from same line and subsequent lines
|
|
117
|
+
if (/payload\s*:/.test(valLine)) {
|
|
118
|
+
// Same-line extraction
|
|
119
|
+
const paramMatch = valLine.match(/(\w+)\s*:\s*Joi\./g);
|
|
120
|
+
if (paramMatch) {
|
|
121
|
+
for (const pm of paramMatch) {
|
|
122
|
+
const name = (_c = pm.match(/(\w+)\s*:/)) === null || _c === void 0 ? void 0 : _c[1];
|
|
123
|
+
if (name)
|
|
124
|
+
payloadParams.push(name);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
// Multi-line extraction: scan subsequent lines for fieldName: Joi. patterns
|
|
128
|
+
for (let q = k + 1; q < Math.min(k + 16, lines.length); q++) {
|
|
129
|
+
const subLine = lines[q];
|
|
130
|
+
if (/}\s*[),]/.test(subLine) || /]\s*,/.test(subLine))
|
|
131
|
+
break;
|
|
132
|
+
const fieldMatch = subLine.match(/(\w+)\s*:\s*Joi\./g);
|
|
133
|
+
if (fieldMatch) {
|
|
134
|
+
for (const fm of fieldMatch) {
|
|
135
|
+
const name = (_d = fm.match(/(\w+)\s*:/)) === null || _d === void 0 ? void 0 : _d[1];
|
|
136
|
+
if (name && !payloadParams.includes(name))
|
|
137
|
+
payloadParams.push(name);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
if (queryParams.length > 0 || payloadParams.length > 0) {
|
|
144
|
+
validation = { queryParams, payloadParams };
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
if (path) {
|
|
149
|
+
routes.push({ method, path, auth, validation, sourceFile: filePath, line: i + 1 });
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
return routes;
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Detect Boom error responses.
|
|
156
|
+
*/
|
|
157
|
+
function detectBoomErrors(sourceText, filePath) {
|
|
158
|
+
const errors = [];
|
|
159
|
+
const lines = sourceText.split('\n');
|
|
160
|
+
for (let i = 0; i < lines.length; i++) {
|
|
161
|
+
const line = lines[i];
|
|
162
|
+
const match = line.match(/Boom\.(\w+)\s*\(/);
|
|
163
|
+
if (match) {
|
|
164
|
+
const errorType = match[1];
|
|
165
|
+
errors.push({
|
|
166
|
+
errorType,
|
|
167
|
+
statusCode: BOOM_STATUS_MAP[errorType],
|
|
168
|
+
sourceFile: filePath,
|
|
169
|
+
line: i + 1,
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
return errors;
|
|
174
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Mongoose schema/model detector (Feature 27, Sub-PR 6)
|
|
3
|
+
*
|
|
4
|
+
* Detects:
|
|
5
|
+
* 1. mongoose.Schema({...}) — field definitions, validation rules
|
|
6
|
+
* 2. mongoose.model('Name', schema) — model creation
|
|
7
|
+
* 3. .methods.* — instance method definitions
|
|
8
|
+
* 4. .pre()/.post() hooks — lifecycle hooks
|
|
9
|
+
* 5. .plugin(validator) — plugin registrations
|
|
10
|
+
*/
|
|
11
|
+
export interface MongooseField {
|
|
12
|
+
name: string;
|
|
13
|
+
type: string;
|
|
14
|
+
required?: boolean;
|
|
15
|
+
unique?: boolean;
|
|
16
|
+
enumValues?: string[];
|
|
17
|
+
}
|
|
18
|
+
export interface MongooseModel {
|
|
19
|
+
modelName: string;
|
|
20
|
+
schemaVariable?: string;
|
|
21
|
+
fields: MongooseField[];
|
|
22
|
+
methods: string[];
|
|
23
|
+
hooks: Array<{
|
|
24
|
+
stage: 'pre' | 'post';
|
|
25
|
+
event: string;
|
|
26
|
+
}>;
|
|
27
|
+
plugins: string[];
|
|
28
|
+
sourceFile: string;
|
|
29
|
+
line?: number;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Detect Mongoose model/schema definitions from JS/TS source text.
|
|
33
|
+
*/
|
|
34
|
+
export declare function detectMongooseModels(sourceText: string, filePath: string): MongooseModel[];
|
|
35
|
+
/**
|
|
36
|
+
* Detect Express error handlers (4-argument middleware).
|
|
37
|
+
*/
|
|
38
|
+
export interface ExpressErrorHandler {
|
|
39
|
+
functionName?: string;
|
|
40
|
+
errorTypes: string[];
|
|
41
|
+
statusCodes: number[];
|
|
42
|
+
sourceFile: string;
|
|
43
|
+
line?: number;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Detect Express 4-argument error handler middleware.
|
|
47
|
+
* Pattern: function(err, req, res, next) or (err, req, res, next) =>
|
|
48
|
+
*/
|
|
49
|
+
export declare function detectExpressErrorHandlers(sourceText: string, filePath: string): ExpressErrorHandler[];
|
|
50
|
+
/**
|
|
51
|
+
* Detect Express middleware auth patterns.
|
|
52
|
+
* Pattern: router.use(auth.required) or router.use('/path', auth.optional, subRouter)
|
|
53
|
+
*/
|
|
54
|
+
export interface ExpressAuthMiddleware {
|
|
55
|
+
/** 'required' or 'optional' */
|
|
56
|
+
authType: 'required' | 'optional';
|
|
57
|
+
/** The path prefix this middleware applies to */
|
|
58
|
+
pathPrefix?: string;
|
|
59
|
+
/** Source pattern text */
|
|
60
|
+
sourcePattern: string;
|
|
61
|
+
sourceFile: string;
|
|
62
|
+
line?: number;
|
|
63
|
+
}
|
|
64
|
+
export declare function detectExpressAuthMiddleware(sourceText: string, filePath: string): ExpressAuthMiddleware[];
|
|
65
|
+
//# sourceMappingURL=mongooseDetector.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mongooseDetector.d.ts","sourceRoot":"","sources":["../../../../src/languages/javascript/mongooseDetector.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;CACvB;AAED,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,MAAM,EAAE,aAAa,EAAE,CAAC;IACxB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,KAAK,EAAE,KAAK,CAAC;QAAE,KAAK,EAAE,KAAK,GAAG,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACvD,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,aAAa,EAAE,CA2E1F;AAwED;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED;;;GAGG;AACH,wBAAgB,0BAA0B,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,mBAAmB,EAAE,CAuCtG;AAED;;;GAGG;AACH,MAAM,WAAW,qBAAqB;IACpC,+BAA+B;IAC/B,QAAQ,EAAE,UAAU,GAAG,UAAU,CAAC;IAClC,iDAAiD;IACjD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,0BAA0B;IAC1B,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,wBAAgB,2BAA2B,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,qBAAqB,EAAE,CA6CzG"}
|
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Mongoose schema/model detector (Feature 27, Sub-PR 6)
|
|
4
|
+
*
|
|
5
|
+
* Detects:
|
|
6
|
+
* 1. mongoose.Schema({...}) — field definitions, validation rules
|
|
7
|
+
* 2. mongoose.model('Name', schema) — model creation
|
|
8
|
+
* 3. .methods.* — instance method definitions
|
|
9
|
+
* 4. .pre()/.post() hooks — lifecycle hooks
|
|
10
|
+
* 5. .plugin(validator) — plugin registrations
|
|
11
|
+
*/
|
|
12
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
|
+
exports.detectMongooseModels = detectMongooseModels;
|
|
14
|
+
exports.detectExpressErrorHandlers = detectExpressErrorHandlers;
|
|
15
|
+
exports.detectExpressAuthMiddleware = detectExpressAuthMiddleware;
|
|
16
|
+
/**
|
|
17
|
+
* Detect Mongoose model/schema definitions from JS/TS source text.
|
|
18
|
+
*/
|
|
19
|
+
function detectMongooseModels(sourceText, filePath) {
|
|
20
|
+
var _a, _b, _c, _d;
|
|
21
|
+
const models = [];
|
|
22
|
+
const lines = sourceText.split('\n');
|
|
23
|
+
// Track schema variables and their fields
|
|
24
|
+
const schemaVars = new Map();
|
|
25
|
+
// Track methods, hooks, plugins per schema var
|
|
26
|
+
const schemaMethods = new Map();
|
|
27
|
+
const schemaHooks = new Map();
|
|
28
|
+
const schemaPlugins = new Map();
|
|
29
|
+
for (let i = 0; i < lines.length; i++) {
|
|
30
|
+
const line = lines[i];
|
|
31
|
+
// new mongoose.Schema({...}) or new Schema({...})
|
|
32
|
+
const schemaMatch = line.match(/(?:const|let|var)\s+(\w+)\s*=\s*new\s+(?:mongoose\.)?Schema\s*\(/);
|
|
33
|
+
if (schemaMatch) {
|
|
34
|
+
const varName = schemaMatch[1];
|
|
35
|
+
const fields = extractSchemaFields(sourceText, i);
|
|
36
|
+
schemaVars.set(varName, { fields, line: i + 1 });
|
|
37
|
+
continue;
|
|
38
|
+
}
|
|
39
|
+
// mongoose.model('Name', schema)
|
|
40
|
+
const modelMatch = line.match(/mongoose\.model\s*\(\s*['"](\w+)['"]\s*,\s*(\w+)/);
|
|
41
|
+
if (modelMatch) {
|
|
42
|
+
const modelName = modelMatch[1];
|
|
43
|
+
const schemaVar = modelMatch[2];
|
|
44
|
+
const schemaInfo = schemaVars.get(schemaVar);
|
|
45
|
+
models.push({
|
|
46
|
+
modelName,
|
|
47
|
+
schemaVariable: schemaVar,
|
|
48
|
+
fields: (_a = schemaInfo === null || schemaInfo === void 0 ? void 0 : schemaInfo.fields) !== null && _a !== void 0 ? _a : [],
|
|
49
|
+
methods: (_b = schemaMethods.get(schemaVar)) !== null && _b !== void 0 ? _b : [],
|
|
50
|
+
hooks: (_c = schemaHooks.get(schemaVar)) !== null && _c !== void 0 ? _c : [],
|
|
51
|
+
plugins: (_d = schemaPlugins.get(schemaVar)) !== null && _d !== void 0 ? _d : [],
|
|
52
|
+
sourceFile: filePath,
|
|
53
|
+
line: i + 1,
|
|
54
|
+
});
|
|
55
|
+
continue;
|
|
56
|
+
}
|
|
57
|
+
// schema.methods.methodName = function
|
|
58
|
+
const methodMatch = line.match(/(\w+)\.methods\.(\w+)\s*=/);
|
|
59
|
+
if (methodMatch) {
|
|
60
|
+
const varName = methodMatch[1];
|
|
61
|
+
if (!schemaMethods.has(varName))
|
|
62
|
+
schemaMethods.set(varName, []);
|
|
63
|
+
schemaMethods.get(varName).push(methodMatch[2]);
|
|
64
|
+
continue;
|
|
65
|
+
}
|
|
66
|
+
// schema.pre('save', ...) or schema.post('save', ...)
|
|
67
|
+
const hookMatch = line.match(/(\w+)\.(pre|post)\s*\(\s*['"](\w+)['"]/);
|
|
68
|
+
if (hookMatch) {
|
|
69
|
+
const varName = hookMatch[1];
|
|
70
|
+
if (!schemaHooks.has(varName))
|
|
71
|
+
schemaHooks.set(varName, []);
|
|
72
|
+
schemaHooks.get(varName).push({
|
|
73
|
+
stage: hookMatch[2],
|
|
74
|
+
event: hookMatch[3],
|
|
75
|
+
});
|
|
76
|
+
continue;
|
|
77
|
+
}
|
|
78
|
+
// schema.plugin(uniqueValidator)
|
|
79
|
+
const pluginMatch = line.match(/(\w+)\.plugin\s*\(\s*(\w+)/);
|
|
80
|
+
if (pluginMatch) {
|
|
81
|
+
const varName = pluginMatch[1];
|
|
82
|
+
if (!schemaPlugins.has(varName))
|
|
83
|
+
schemaPlugins.set(varName, []);
|
|
84
|
+
schemaPlugins.get(varName).push(pluginMatch[2]);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
return models;
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Extract field definitions from a schema constructor.
|
|
91
|
+
* Simple regex extraction — handles the most common patterns.
|
|
92
|
+
*/
|
|
93
|
+
function extractSchemaFields(source, startLine) {
|
|
94
|
+
var _a;
|
|
95
|
+
const fields = [];
|
|
96
|
+
const lines = source.split('\n');
|
|
97
|
+
// Find the opening brace of the schema definition
|
|
98
|
+
let braceDepth = 0;
|
|
99
|
+
let inSchema = false;
|
|
100
|
+
let schemaBody = '';
|
|
101
|
+
for (let i = startLine; i < Math.min(startLine + 50, lines.length); i++) {
|
|
102
|
+
const line = lines[i];
|
|
103
|
+
for (const ch of line) {
|
|
104
|
+
if (ch === '(' || ch === '{')
|
|
105
|
+
braceDepth++;
|
|
106
|
+
if (ch === ')' || ch === '}')
|
|
107
|
+
braceDepth--;
|
|
108
|
+
if (braceDepth >= 2 && !inSchema) {
|
|
109
|
+
inSchema = true;
|
|
110
|
+
}
|
|
111
|
+
if (inSchema)
|
|
112
|
+
schemaBody += ch;
|
|
113
|
+
if (inSchema && braceDepth < 2) {
|
|
114
|
+
inSchema = false;
|
|
115
|
+
break;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
if (schemaBody && !inSchema)
|
|
119
|
+
break;
|
|
120
|
+
if (inSchema)
|
|
121
|
+
schemaBody += '\n';
|
|
122
|
+
}
|
|
123
|
+
// Parse field definitions from the schema body
|
|
124
|
+
// Pattern: fieldName: { type: Type, required: true, unique: true, enum: [...] }
|
|
125
|
+
const fieldPattern = /(\w+)\s*:\s*\{([^}]+)\}/g;
|
|
126
|
+
let match;
|
|
127
|
+
while ((match = fieldPattern.exec(schemaBody)) !== null) {
|
|
128
|
+
const name = match[1];
|
|
129
|
+
const body = match[2];
|
|
130
|
+
const typeMatch = body.match(/type\s*:\s*(\w+)/);
|
|
131
|
+
const required = /required\s*:\s*true/.test(body);
|
|
132
|
+
const unique = /unique\s*:\s*true/.test(body);
|
|
133
|
+
const enumMatch = body.match(/enum\s*:\s*\[([^\]]+)\]/);
|
|
134
|
+
const field = {
|
|
135
|
+
name,
|
|
136
|
+
type: (_a = typeMatch === null || typeMatch === void 0 ? void 0 : typeMatch[1]) !== null && _a !== void 0 ? _a : 'Mixed',
|
|
137
|
+
};
|
|
138
|
+
if (required)
|
|
139
|
+
field.required = true;
|
|
140
|
+
if (unique)
|
|
141
|
+
field.unique = true;
|
|
142
|
+
if (enumMatch) {
|
|
143
|
+
field.enumValues = enumMatch[1].split(',').map((s) => s.trim().replace(/['"]/g, '')).filter(Boolean);
|
|
144
|
+
}
|
|
145
|
+
fields.push(field);
|
|
146
|
+
}
|
|
147
|
+
// Also handle shorthand: fieldName: Type (e.g., fieldName: String)
|
|
148
|
+
const shorthandPattern = /(\w+)\s*:\s*(String|Number|Boolean|Date|ObjectId|Buffer|Mixed|Map)\b/g;
|
|
149
|
+
while ((match = shorthandPattern.exec(schemaBody)) !== null) {
|
|
150
|
+
const name = match[1];
|
|
151
|
+
// Skip if already captured as an object definition
|
|
152
|
+
if (!fields.some((f) => f.name === name)) {
|
|
153
|
+
fields.push({ name, type: match[2] });
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
return fields;
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Detect Express 4-argument error handler middleware.
|
|
160
|
+
* Pattern: function(err, req, res, next) or (err, req, res, next) =>
|
|
161
|
+
*/
|
|
162
|
+
function detectExpressErrorHandlers(sourceText, filePath) {
|
|
163
|
+
const handlers = [];
|
|
164
|
+
const lines = sourceText.split('\n');
|
|
165
|
+
// Pattern: matches 4-argument functions (err, req, res, next)
|
|
166
|
+
const errorHandlerPattern = /(?:function\s+(\w+))?\s*\(\s*(?:err|error)\s*,\s*req\s*,\s*res\s*,\s*next\s*\)/;
|
|
167
|
+
for (let i = 0; i < lines.length; i++) {
|
|
168
|
+
const line = lines[i];
|
|
169
|
+
const match = line.match(errorHandlerPattern);
|
|
170
|
+
if (!match)
|
|
171
|
+
continue;
|
|
172
|
+
const functionName = match[1];
|
|
173
|
+
const errorTypes = [];
|
|
174
|
+
const statusCodes = [];
|
|
175
|
+
// Scan ahead for error type checks and status codes
|
|
176
|
+
for (let j = i; j < Math.min(i + 30, lines.length); j++) {
|
|
177
|
+
const scanLine = lines[j];
|
|
178
|
+
// err.name === 'ValidationError'
|
|
179
|
+
const errorTypeMatch = scanLine.match(/err(?:or)?\.name\s*===?\s*['"](\w+)['"]/);
|
|
180
|
+
if (errorTypeMatch)
|
|
181
|
+
errorTypes.push(errorTypeMatch[1]);
|
|
182
|
+
// res.status(404)
|
|
183
|
+
const statusMatch = scanLine.match(/res\.status\s*\(\s*(\d{3})\s*\)/);
|
|
184
|
+
if (statusMatch)
|
|
185
|
+
statusCodes.push(parseInt(statusMatch[1], 10));
|
|
186
|
+
}
|
|
187
|
+
handlers.push({
|
|
188
|
+
functionName,
|
|
189
|
+
errorTypes,
|
|
190
|
+
statusCodes,
|
|
191
|
+
sourceFile: filePath,
|
|
192
|
+
line: i + 1,
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
return handlers;
|
|
196
|
+
}
|
|
197
|
+
function detectExpressAuthMiddleware(sourceText, filePath) {
|
|
198
|
+
const middleware = [];
|
|
199
|
+
const lines = sourceText.split('\n');
|
|
200
|
+
for (let i = 0; i < lines.length; i++) {
|
|
201
|
+
const line = lines[i];
|
|
202
|
+
// router.use(auth.required) or app.use(auth.required)
|
|
203
|
+
const simpleAuth = line.match(/(?:router|app)\.use\s*\(\s*auth\.(required|optional)/);
|
|
204
|
+
if (simpleAuth) {
|
|
205
|
+
middleware.push({
|
|
206
|
+
authType: simpleAuth[1],
|
|
207
|
+
sourcePattern: simpleAuth[0],
|
|
208
|
+
sourceFile: filePath,
|
|
209
|
+
line: i + 1,
|
|
210
|
+
});
|
|
211
|
+
continue;
|
|
212
|
+
}
|
|
213
|
+
// router.use('/path', auth.required, router)
|
|
214
|
+
const pathAuth = line.match(/(?:router|app)\.use\s*\(\s*['"]([^'"]+)['"]\s*,\s*auth\.(required|optional)/);
|
|
215
|
+
if (pathAuth) {
|
|
216
|
+
middleware.push({
|
|
217
|
+
authType: pathAuth[2],
|
|
218
|
+
pathPrefix: pathAuth[1],
|
|
219
|
+
sourcePattern: pathAuth[0],
|
|
220
|
+
sourceFile: filePath,
|
|
221
|
+
line: i + 1,
|
|
222
|
+
});
|
|
223
|
+
continue;
|
|
224
|
+
}
|
|
225
|
+
// passport.authenticate('jwt', { session: false })
|
|
226
|
+
const passportAuth = line.match(/passport\.authenticate\s*\(\s*['"](\w+)['"]/);
|
|
227
|
+
if (passportAuth) {
|
|
228
|
+
middleware.push({
|
|
229
|
+
authType: 'required',
|
|
230
|
+
sourcePattern: passportAuth[0],
|
|
231
|
+
sourceFile: filePath,
|
|
232
|
+
line: i + 1,
|
|
233
|
+
});
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
return middleware;
|
|
237
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Vue.js/Vuex pattern detector (Feature 27, Sub-PR 8)
|
|
3
|
+
*
|
|
4
|
+
* Detects:
|
|
5
|
+
* 1. axios.defaults.baseURL — global base URL
|
|
6
|
+
* 2. Vuex actions with API calls (ApiService.get, axios.get, etc.)
|
|
7
|
+
* 3. this.$store.dispatch('actionName') — component dispatches
|
|
8
|
+
* 4. ApiService.get('resource') — service-layer API calls
|
|
9
|
+
*/
|
|
10
|
+
export interface VueApiCall {
|
|
11
|
+
actionName?: string;
|
|
12
|
+
/** Resolved string value when actionName is a constant (e.g., FETCH_ARTICLES → 'fetchArticles') */
|
|
13
|
+
resolvedName?: string;
|
|
14
|
+
method: string;
|
|
15
|
+
urlPattern: string;
|
|
16
|
+
baseUrl?: string;
|
|
17
|
+
sourceFile: string;
|
|
18
|
+
line?: number;
|
|
19
|
+
}
|
|
20
|
+
export interface VuexDispatch {
|
|
21
|
+
actionName: string;
|
|
22
|
+
sourceFile: string;
|
|
23
|
+
line?: number;
|
|
24
|
+
}
|
|
25
|
+
export interface VueBaseUrl {
|
|
26
|
+
url: string;
|
|
27
|
+
sourceFile: string;
|
|
28
|
+
line?: number;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Detect axios.defaults.baseURL settings.
|
|
32
|
+
*/
|
|
33
|
+
export declare function detectAxiosBaseUrl(sourceText: string, filePath: string): VueBaseUrl | undefined;
|
|
34
|
+
/**
|
|
35
|
+
* Detect Vuex action definitions with API calls.
|
|
36
|
+
*/
|
|
37
|
+
export declare function detectVuexActions(sourceText: string, filePath: string): VueApiCall[];
|
|
38
|
+
/**
|
|
39
|
+
* Detect this.$store.dispatch() or store.dispatch() calls.
|
|
40
|
+
*/
|
|
41
|
+
export declare function detectVuexDispatches(sourceText: string, filePath: string): VuexDispatch[];
|
|
42
|
+
//# sourceMappingURL=vueDetector.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vueDetector.d.ts","sourceRoot":"","sources":["../../../../src/languages/javascript/vueDetector.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,MAAM,WAAW,UAAU;IACzB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,mGAAmG;IACnG,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,YAAY;IAC3B,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,UAAU;IACzB,GAAG,EAAE,MAAM,CAAC;IACZ,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,UAAU,GAAG,SAAS,CAO/F;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,UAAU,EAAE,CAoEpF;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,YAAY,EAAE,CAkBzF"}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Vue.js/Vuex pattern detector (Feature 27, Sub-PR 8)
|
|
4
|
+
*
|
|
5
|
+
* Detects:
|
|
6
|
+
* 1. axios.defaults.baseURL — global base URL
|
|
7
|
+
* 2. Vuex actions with API calls (ApiService.get, axios.get, etc.)
|
|
8
|
+
* 3. this.$store.dispatch('actionName') — component dispatches
|
|
9
|
+
* 4. ApiService.get('resource') — service-layer API calls
|
|
10
|
+
*/
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.detectAxiosBaseUrl = detectAxiosBaseUrl;
|
|
13
|
+
exports.detectVuexActions = detectVuexActions;
|
|
14
|
+
exports.detectVuexDispatches = detectVuexDispatches;
|
|
15
|
+
/**
|
|
16
|
+
* Detect axios.defaults.baseURL settings.
|
|
17
|
+
*/
|
|
18
|
+
function detectAxiosBaseUrl(sourceText, filePath) {
|
|
19
|
+
const match = sourceText.match(/axios\.defaults\.baseURL\s*=\s*['"`]([^'"`]+)['"`]/);
|
|
20
|
+
if (match) {
|
|
21
|
+
const line = sourceText.substring(0, match.index).split('\n').length;
|
|
22
|
+
return { url: match[1], sourceFile: filePath, line };
|
|
23
|
+
}
|
|
24
|
+
return undefined;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Detect Vuex action definitions with API calls.
|
|
28
|
+
*/
|
|
29
|
+
function detectVuexActions(sourceText, filePath) {
|
|
30
|
+
const calls = [];
|
|
31
|
+
const lines = sourceText.split('\n');
|
|
32
|
+
// Pass 1: Build a map of constant name → string value.
|
|
33
|
+
// Matches patterns like:
|
|
34
|
+
// const FETCH_ARTICLES = 'fetchArticles'
|
|
35
|
+
// export const FETCH_ARTICLES = "fetchArticles"
|
|
36
|
+
const constantMap = new Map();
|
|
37
|
+
for (const line of lines) {
|
|
38
|
+
const constMatch = line.match(/(?:export\s+)?const\s+([A-Z_][A-Z0-9_]*)\s*=\s*['"]([^'"]+)['"]/);
|
|
39
|
+
if (constMatch) {
|
|
40
|
+
constantMap.set(constMatch[1], constMatch[2]);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
// Pass 2: Detect action definitions and their API calls.
|
|
44
|
+
let currentAction = '';
|
|
45
|
+
let currentResolvedName;
|
|
46
|
+
for (let i = 0; i < lines.length; i++) {
|
|
47
|
+
const line = lines[i];
|
|
48
|
+
// Vuex action definition: [ACTION_NAME]({ commit }, payload) {
|
|
49
|
+
// or: actionName({ commit }) {
|
|
50
|
+
const actionMatch = line.match(/(?:\[(\w+)\]|(\w+))\s*\(\s*\{\s*(?:commit|dispatch|state|getters|rootState)/);
|
|
51
|
+
if (actionMatch) {
|
|
52
|
+
currentAction = actionMatch[1] || actionMatch[2] || '';
|
|
53
|
+
// If using bracket syntax with a constant, resolve to its string value
|
|
54
|
+
if (actionMatch[1] && constantMap.has(actionMatch[1])) {
|
|
55
|
+
currentResolvedName = constantMap.get(actionMatch[1]);
|
|
56
|
+
}
|
|
57
|
+
else {
|
|
58
|
+
currentResolvedName = undefined;
|
|
59
|
+
}
|
|
60
|
+
continue;
|
|
61
|
+
}
|
|
62
|
+
// ApiService.get/post/put/delete('resource')
|
|
63
|
+
const apiServiceMatch = line.match(/ApiService\.(get|post|put|patch|delete)\s*\(\s*['"`]([^'"`]+)['"`]/i);
|
|
64
|
+
if (apiServiceMatch) {
|
|
65
|
+
calls.push({
|
|
66
|
+
actionName: currentAction || undefined,
|
|
67
|
+
resolvedName: currentResolvedName,
|
|
68
|
+
method: apiServiceMatch[1].toUpperCase(),
|
|
69
|
+
urlPattern: apiServiceMatch[2],
|
|
70
|
+
sourceFile: filePath,
|
|
71
|
+
line: i + 1,
|
|
72
|
+
});
|
|
73
|
+
continue;
|
|
74
|
+
}
|
|
75
|
+
// axios.get/post/put/delete('url')
|
|
76
|
+
const axiosMatch = line.match(/axios\.(get|post|put|patch|delete)\s*\(\s*['"`]([^'"`]+)['"`]/i);
|
|
77
|
+
if (axiosMatch) {
|
|
78
|
+
calls.push({
|
|
79
|
+
actionName: currentAction || undefined,
|
|
80
|
+
resolvedName: currentResolvedName,
|
|
81
|
+
method: axiosMatch[1].toUpperCase(),
|
|
82
|
+
urlPattern: axiosMatch[2],
|
|
83
|
+
sourceFile: filePath,
|
|
84
|
+
line: i + 1,
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
return calls;
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Detect this.$store.dispatch() or store.dispatch() calls.
|
|
92
|
+
*/
|
|
93
|
+
function detectVuexDispatches(sourceText, filePath) {
|
|
94
|
+
const dispatches = [];
|
|
95
|
+
const lines = sourceText.split('\n');
|
|
96
|
+
for (let i = 0; i < lines.length; i++) {
|
|
97
|
+
const line = lines[i];
|
|
98
|
+
// this.$store.dispatch('ACTION_NAME') or store.dispatch('actionName')
|
|
99
|
+
const match = line.match(/(?:this\.\$store|store)\.dispatch\s*\(\s*['"](\w+)['"]/);
|
|
100
|
+
if (match) {
|
|
101
|
+
dispatches.push({
|
|
102
|
+
actionName: match[1],
|
|
103
|
+
sourceFile: filePath,
|
|
104
|
+
line: i + 1,
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
return dispatches;
|
|
109
|
+
}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Python language analyzer using tree-sitter-python.
|
|
3
3
|
*/
|
|
4
4
|
import type { LanguageAnalyzer } from '../../ast/languageAnalyzer';
|
|
5
|
-
import type { SupportedLanguage, ParsedSourceFile, SemanticModel, ResolvedHttpInteraction, SemanticAssertion, BusinessRuleRef, FlowRef, AnalysisContext } from '../../ast/astTypes';
|
|
5
|
+
import type { SupportedLanguage, ParsedSourceFile, SemanticModel, ResolvedHttpInteraction, SemanticAssertion, BusinessRuleRef, FlowRef, AnalysisContext, DecoratorInfo, SecurityClassification } from '../../ast/astTypes';
|
|
6
6
|
export declare class PythonAnalyzer implements LanguageAnalyzer {
|
|
7
7
|
readonly language: SupportedLanguage;
|
|
8
8
|
parse(filePath: string, content: string): ParsedSourceFile;
|
|
@@ -10,6 +10,10 @@ export declare class PythonAnalyzer implements LanguageAnalyzer {
|
|
|
10
10
|
extractHttpInteractions(model: SemanticModel, _ctx: AnalysisContext): ResolvedHttpInteraction[];
|
|
11
11
|
extractAssertions(model: SemanticModel): SemanticAssertion[];
|
|
12
12
|
extractBusinessRuleRefs(model: SemanticModel): BusinessRuleRef[];
|
|
13
|
-
extractFlowRefs(
|
|
13
|
+
extractFlowRefs(model: SemanticModel): FlowRef[];
|
|
14
14
|
}
|
|
15
|
+
/**
|
|
16
|
+
* Classify JWT/auth security from decorator information.
|
|
17
|
+
*/
|
|
18
|
+
export declare function classifyFlaskSecurity(decorators: DecoratorInfo[]): SecurityClassification | undefined;
|
|
15
19
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/languages/python/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AACnE,OAAO,KAAK,EACV,iBAAiB,EACjB,gBAAgB,EAChB,aAAa,EAIb,uBAAuB,EACvB,iBAAiB,EACjB,eAAe,EACf,OAAO,EACP,eAAe,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/languages/python/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AACnE,OAAO,KAAK,EACV,iBAAiB,EACjB,gBAAgB,EAChB,aAAa,EAIb,uBAAuB,EACvB,iBAAiB,EACjB,eAAe,EACf,OAAO,EACP,eAAe,EAEf,aAAa,EAEb,sBAAsB,EACvB,MAAM,oBAAoB,CAAC;AAmC5B,qBAAa,cAAe,YAAW,gBAAgB;IACrD,QAAQ,CAAC,QAAQ,EAAE,iBAAiB,CAAY;IAEhD,KAAK,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,gBAAgB;IAc1D,kBAAkB,CAAC,MAAM,EAAE,gBAAgB,EAAE,QAAQ,EAAE,eAAe,GAAG,aAAa;IA4CtF,uBAAuB,CAAC,KAAK,EAAE,aAAa,EAAE,IAAI,EAAE,eAAe,GAAG,uBAAuB,EAAE;IAwB/F,iBAAiB,CAAC,KAAK,EAAE,aAAa,GAAG,iBAAiB,EAAE;IAG5D,uBAAuB,CAAC,KAAK,EAAE,aAAa,GAAG,eAAe,EAAE;IAGhE,eAAe,CAAC,KAAK,EAAE,aAAa,GAAG,OAAO,EAAE;CAqBjD;AA2WD;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,UAAU,EAAE,aAAa,EAAE,GAAG,sBAAsB,GAAG,SAAS,CAarG"}
|