api-tests-coverage 1.0.14 → 1.0.16
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/dashboard/dist/index.html +1 -1
- package/dist/src/ast/astTypes.d.ts +86 -0
- package/dist/src/ast/astTypes.d.ts.map +1 -1
- 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 +4 -0
- 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/javascript/angularDetector.d.ts +74 -0
- package/dist/src/languages/javascript/angularDetector.d.ts.map +1 -0
- package/dist/src/languages/javascript/angularDetector.js +194 -0
- 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 +131 -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 +40 -0
- package/dist/src/languages/javascript/vueDetector.d.ts.map +1 -0
- package/dist/src/languages/javascript/vueDetector.js +87 -0
- package/dist/src/languages/python/index.d.ts +5 -1
- package/dist/src/languages/python/index.d.ts.map +1 -1
- package/dist/src/languages/python/index.js +167 -2
- 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/stages/ast/astStage.d.ts.map +1 -1
- package/dist/src/pipeline/stages/ast/astStage.js +6 -0
- 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 +83 -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 +10 -1
- package/dist/src/pipeline/stages/ast/optionalAuthUnifier.d.ts +39 -0
- package/dist/src/pipeline/stages/ast/optionalAuthUnifier.d.ts.map +1 -0
- package/dist/src/pipeline/stages/ast/optionalAuthUnifier.js +81 -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 +77 -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 +238 -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 +74 -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 +55 -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 +120 -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/tia/testLayerClassifier.d.ts.map +1 -1
- package/dist/src/pipeline/stages/tia/testLayerClassifier.js +5 -0
- package/package.json +1 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"testPatternDetector.d.ts","sourceRoot":"","sources":["../../../../src/languages/python/testPatternDetector.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAmB,MAAM,oBAAoB,CAAC;AAK5E,MAAM,WAAW,iBAAiB;IAChC,qDAAqD;IACrD,SAAS,EAAE,MAAM,CAAC;IAClB,sDAAsD;IACtD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,4BAA4B;IAC5B,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,oCAAoC;IACpC,mBAAmB,EAAE,MAAM,EAAE,CAAC;IAC9B,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED;;;GAGG;AACH,wBAAgB,yBAAyB,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,iBAAiB,EAAE,CAiEnG;AAID,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAiBD;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,cAAc,EAAE,CA6BzF;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,cAAc,EAAE,GAAG,gBAAgB,EAAE,CAUnF;AAID,MAAM,WAAW,aAAa;IAC5B,mCAAmC;IACnC,IAAI,EAAE,MAAM,CAAC;IACb,gEAAgE;IAChE,KAAK,EAAE,MAAM,CAAC;IACd,8DAA8D;IAC9D,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,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,CAyC1F;AAID;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAE7D;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAO7D;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAE1D"}
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Python test pattern detector (Feature 27, Sub-PR 4)
|
|
4
|
+
*
|
|
5
|
+
* Detects:
|
|
6
|
+
* 1. Factory Boy factories (factory.Factory subclasses, SubFactory, Meta.model)
|
|
7
|
+
* 2. webtest API calls (TestApp, testapp.get/post_json/put_json/delete)
|
|
8
|
+
* 3. pytest fixture chains (@pytest.fixture, fixture dependencies)
|
|
9
|
+
*/
|
|
10
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
11
|
+
exports.detectFactoryBoyFactories = detectFactoryBoyFactories;
|
|
12
|
+
exports.detectWebtestCalls = detectWebtestCalls;
|
|
13
|
+
exports.webtestCallsToHttpCalls = webtestCallsToHttpCalls;
|
|
14
|
+
exports.detectPytestFixtures = detectPytestFixtures;
|
|
15
|
+
exports.hasWebtestTestApp = hasWebtestTestApp;
|
|
16
|
+
exports.hasRealDbFixtures = hasRealDbFixtures;
|
|
17
|
+
exports.usesFactoryBoy = usesFactoryBoy;
|
|
18
|
+
/**
|
|
19
|
+
* Detect Factory Boy factory classes from source text.
|
|
20
|
+
* Looks for `class XFactory(factory.Factory):` and parses Meta.model, SubFactory, RelatedFactoryList.
|
|
21
|
+
*/
|
|
22
|
+
function detectFactoryBoyFactories(sourceText, filePath) {
|
|
23
|
+
const factories = [];
|
|
24
|
+
const lines = sourceText.split('\n');
|
|
25
|
+
// Regex for class definition inheriting from factory.Factory or factory.DjangoModelFactory etc.
|
|
26
|
+
const classPattern = /^class\s+(\w+)\s*\(\s*(?:factory\.(?:Factory|DjangoModelFactory|SQLAlchemyModelFactory|MongoEngineFactory)|Factory)\s*\)/;
|
|
27
|
+
const metaModelPattern = /model\s*=\s*(\w+)/;
|
|
28
|
+
const subFactoryPattern = /=\s*(?:factory\.)?SubFactory\s*\(\s*['"]?(\w+)/g;
|
|
29
|
+
const relatedFactoryPattern = /=\s*(?:factory\.)?RelatedFactoryList\s*\(\s*['"]?(\w+)/g;
|
|
30
|
+
let currentFactory = null;
|
|
31
|
+
let classIndent = -1;
|
|
32
|
+
for (let i = 0; i < lines.length; i++) {
|
|
33
|
+
const line = lines[i];
|
|
34
|
+
const indent = line.search(/\S/);
|
|
35
|
+
// If we're inside a factory class, check for end of class
|
|
36
|
+
if (currentFactory && indent >= 0 && indent <= classIndent && line.trim().length > 0) {
|
|
37
|
+
factories.push(currentFactory);
|
|
38
|
+
currentFactory = null;
|
|
39
|
+
classIndent = -1;
|
|
40
|
+
}
|
|
41
|
+
const classMatch = line.match(classPattern);
|
|
42
|
+
if (classMatch) {
|
|
43
|
+
if (currentFactory)
|
|
44
|
+
factories.push(currentFactory);
|
|
45
|
+
currentFactory = {
|
|
46
|
+
className: classMatch[1],
|
|
47
|
+
subFactories: [],
|
|
48
|
+
relatedFactoryLists: [],
|
|
49
|
+
sourceFile: filePath,
|
|
50
|
+
line: i + 1,
|
|
51
|
+
};
|
|
52
|
+
classIndent = indent;
|
|
53
|
+
continue;
|
|
54
|
+
}
|
|
55
|
+
if (currentFactory) {
|
|
56
|
+
// Meta.model
|
|
57
|
+
const metaMatch = line.match(metaModelPattern);
|
|
58
|
+
if (metaMatch) {
|
|
59
|
+
currentFactory.modelName = metaMatch[1];
|
|
60
|
+
}
|
|
61
|
+
// SubFactory
|
|
62
|
+
let sfMatch;
|
|
63
|
+
subFactoryPattern.lastIndex = 0;
|
|
64
|
+
while ((sfMatch = subFactoryPattern.exec(line)) !== null) {
|
|
65
|
+
currentFactory.subFactories.push(sfMatch[1]);
|
|
66
|
+
}
|
|
67
|
+
// RelatedFactoryList
|
|
68
|
+
let rfMatch;
|
|
69
|
+
relatedFactoryPattern.lastIndex = 0;
|
|
70
|
+
while ((rfMatch = relatedFactoryPattern.exec(line)) !== null) {
|
|
71
|
+
currentFactory.relatedFactoryLists.push(rfMatch[1]);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
// Push last factory if still open
|
|
76
|
+
if (currentFactory)
|
|
77
|
+
factories.push(currentFactory);
|
|
78
|
+
return factories;
|
|
79
|
+
}
|
|
80
|
+
/** Map webtest methods to HTTP methods */
|
|
81
|
+
const WEBTEST_METHOD_MAP = {
|
|
82
|
+
get: 'GET',
|
|
83
|
+
post: 'POST',
|
|
84
|
+
post_json: 'POST',
|
|
85
|
+
put: 'PUT',
|
|
86
|
+
put_json: 'PUT',
|
|
87
|
+
patch: 'PATCH',
|
|
88
|
+
patch_json: 'PATCH',
|
|
89
|
+
delete: 'DELETE',
|
|
90
|
+
delete_json: 'DELETE',
|
|
91
|
+
head: 'HEAD',
|
|
92
|
+
options: 'OPTIONS',
|
|
93
|
+
};
|
|
94
|
+
/**
|
|
95
|
+
* Detect webtest HTTP calls from source text.
|
|
96
|
+
* Looks for `testapp.get('/path')`, `testapp.post_json('/path', {...})`, etc.
|
|
97
|
+
*/
|
|
98
|
+
function detectWebtestCalls(sourceText, filePath) {
|
|
99
|
+
const calls = [];
|
|
100
|
+
const lines = sourceText.split('\n');
|
|
101
|
+
// Pattern: any_var.METHOD('/path'...) where METHOD is a webtest HTTP method
|
|
102
|
+
const webtestMethods = Object.keys(WEBTEST_METHOD_MAP).join('|');
|
|
103
|
+
const callPattern = new RegExp(`\\w+\\.(${webtestMethods})\\s*\\(\\s*['"]([^'"]+)['"]`, 'g');
|
|
104
|
+
for (let i = 0; i < lines.length; i++) {
|
|
105
|
+
const line = lines[i];
|
|
106
|
+
callPattern.lastIndex = 0;
|
|
107
|
+
let match;
|
|
108
|
+
while ((match = callPattern.exec(line)) !== null) {
|
|
109
|
+
const method = WEBTEST_METHOD_MAP[match[1]];
|
|
110
|
+
if (method) {
|
|
111
|
+
calls.push({
|
|
112
|
+
method,
|
|
113
|
+
path: match[2],
|
|
114
|
+
sourceFile: filePath,
|
|
115
|
+
line: i + 1,
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
return calls;
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Convert webtest API calls into SemanticHttpCall objects.
|
|
124
|
+
*/
|
|
125
|
+
function webtestCallsToHttpCalls(calls) {
|
|
126
|
+
return calls.map((call) => ({
|
|
127
|
+
method: call.method,
|
|
128
|
+
rawPathArg: call.path,
|
|
129
|
+
resolvedPath: call.path,
|
|
130
|
+
normalizedPath: call.path.startsWith('/') ? call.path : undefined,
|
|
131
|
+
resolutionType: 'direct',
|
|
132
|
+
confidence: 'high',
|
|
133
|
+
line: call.line,
|
|
134
|
+
}));
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Detect @pytest.fixture functions and their parameter dependencies.
|
|
138
|
+
*/
|
|
139
|
+
function detectPytestFixtures(sourceText, filePath) {
|
|
140
|
+
const fixtures = [];
|
|
141
|
+
const lines = sourceText.split('\n');
|
|
142
|
+
for (let i = 0; i < lines.length; i++) {
|
|
143
|
+
const line = lines[i];
|
|
144
|
+
// @pytest.fixture or @pytest.fixture(scope='...')
|
|
145
|
+
const fixtureMatch = line.match(/@pytest\.fixture(?:\s*\(([^)]*)\))?/);
|
|
146
|
+
if (!fixtureMatch)
|
|
147
|
+
continue;
|
|
148
|
+
// Parse scope from decorator args
|
|
149
|
+
let scope = 'function';
|
|
150
|
+
if (fixtureMatch[1]) {
|
|
151
|
+
const scopeMatch = fixtureMatch[1].match(/scope\s*=\s*['"](\w+)['"]/);
|
|
152
|
+
if (scopeMatch)
|
|
153
|
+
scope = scopeMatch[1];
|
|
154
|
+
}
|
|
155
|
+
// Find the next def line (typically the line right after the decorator)
|
|
156
|
+
for (let j = i + 1; j < Math.min(i + 5, lines.length); j++) {
|
|
157
|
+
const defMatch = lines[j].match(/def\s+(\w+)\s*\(([^)]*)\)/);
|
|
158
|
+
if (defMatch) {
|
|
159
|
+
const name = defMatch[1];
|
|
160
|
+
const params = defMatch[2]
|
|
161
|
+
.split(',')
|
|
162
|
+
.map((p) => p.trim().split(':')[0].split('=')[0].trim())
|
|
163
|
+
.filter((p) => p.length > 0 && p !== 'request');
|
|
164
|
+
fixtures.push({
|
|
165
|
+
name,
|
|
166
|
+
scope,
|
|
167
|
+
dependencies: params,
|
|
168
|
+
sourceFile: filePath,
|
|
169
|
+
line: j + 1,
|
|
170
|
+
});
|
|
171
|
+
break;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
return fixtures;
|
|
176
|
+
}
|
|
177
|
+
// ─── TestApp Detection ──────────────────────────────────────────────────────
|
|
178
|
+
/**
|
|
179
|
+
* Detect if a file creates a webtest TestApp instance.
|
|
180
|
+
* Looks for `TestApp(app)` or `TestApp(...)`.
|
|
181
|
+
*/
|
|
182
|
+
function hasWebtestTestApp(sourceText) {
|
|
183
|
+
return /TestApp\s*\(/.test(sourceText);
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* Check if a file uses real DB fixtures (not mocked).
|
|
187
|
+
* Looks for pytest fixtures that reference db, database, session, engine, etc.
|
|
188
|
+
*/
|
|
189
|
+
function hasRealDbFixtures(sourceText) {
|
|
190
|
+
// Check for DB fixture names in function parameters
|
|
191
|
+
const dbFixturePattern = /def\s+\w+\s*\([^)]*\b(db|database|dbsession|db_session|engine|session|connection)\b/;
|
|
192
|
+
// Also check for common DB setup patterns
|
|
193
|
+
const dbSetupPattern = /(?:create_all|Base\.metadata|sessionmaker|create_engine|init_db|setup_database)/;
|
|
194
|
+
return dbFixturePattern.test(sourceText) || dbSetupPattern.test(sourceText);
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* Check if a file uses Factory Boy factories.
|
|
198
|
+
*/
|
|
199
|
+
function usesFactoryBoy(sourceText) {
|
|
200
|
+
return /(?:import\s+factory|from\s+factory\s+import|factory\.Factory|factory\.SubFactory)/.test(sourceText);
|
|
201
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"astStage.d.ts","sourceRoot":"","sources":["../../../../../src/pipeline/stages/ast/astStage.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAE3E,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"astStage.d.ts","sourceRoot":"","sources":["../../../../../src/pipeline/stages/ast/astStage.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAE3E,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAmB9C,qBAAa,QAAS,YAAW,aAAa,CAAC,cAAc,CAAC;IAC5D,QAAQ,CAAC,IAAI,EAAG,KAAK,CAAU;IAC/B,QAAQ,CAAC,QAAQ,SAAS;IAEpB,OAAO,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,cAAc,CAAC;CAoLjE"}
|
|
@@ -47,6 +47,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
47
47
|
exports.AstStage = void 0;
|
|
48
48
|
const astAnalysisOrchestrator_1 = require("../../../ast/astAnalysisOrchestrator");
|
|
49
49
|
const crossFileResolver_1 = require("./crossFileResolver");
|
|
50
|
+
const crossFileResolutionPass_1 = require("./crossFileResolutionPass");
|
|
50
51
|
const abstractLayerTraversal_1 = require("./abstractLayerTraversal");
|
|
51
52
|
const graphBuilder_1 = require("./graphBuilder");
|
|
52
53
|
const fileClassifier_1 = require("../../../discovery/fileClassifier");
|
|
@@ -130,6 +131,8 @@ class AstStage {
|
|
|
130
131
|
}
|
|
131
132
|
// Phase 2: Build cross-file symbol table
|
|
132
133
|
const crossFileTable = (0, crossFileResolver_1.buildCrossFileSymbolTable)(models, context.projectRoot);
|
|
134
|
+
// Phase 2b: Run cross-file resolution pass (Feature 27)
|
|
135
|
+
const crossFileResolutionResult = (0, crossFileResolutionPass_1.runCrossFileResolution)(crossFileTable, context.projectRoot, artifacts.apiFrameworks, allSourceFiles);
|
|
133
136
|
// Phase 3: Run abstract layer traversal for test files
|
|
134
137
|
const traversalResults = new Map();
|
|
135
138
|
const depthCap = context.config.traversalDepthCap;
|
|
@@ -199,6 +202,8 @@ class AstStage {
|
|
|
199
202
|
traversalResultCount: traversalResults.size,
|
|
200
203
|
graphNodesAdded: nodes.length,
|
|
201
204
|
graphEdgesAdded: edges.length,
|
|
205
|
+
crossFileResolversRun: crossFileResolutionResult.resolverResults.length,
|
|
206
|
+
crossFileEntriesAdded: crossFileResolutionResult.totalEntriesAdded,
|
|
202
207
|
},
|
|
203
208
|
};
|
|
204
209
|
context.diagnostics.set('ast', diagnostics);
|
|
@@ -209,6 +214,7 @@ class AstStage {
|
|
|
209
214
|
traversalResults,
|
|
210
215
|
analyzedFiles: filesScanned,
|
|
211
216
|
skippedFiles: filesSkipped,
|
|
217
|
+
crossFileResolutionDiagnostics: crossFileResolutionResult.resolverResults,
|
|
212
218
|
};
|
|
213
219
|
context.stageOutputs.set('ast', output);
|
|
214
220
|
return output;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Base URL composer (Feature 27, Sub-PR 9)
|
|
3
|
+
*
|
|
4
|
+
* Unified URL composition across all frameworks:
|
|
5
|
+
* - Flask: Blueprint url_prefix + route path
|
|
6
|
+
* - Express: app.use mount prefix + router path + route path
|
|
7
|
+
* - Spring: @RequestMapping class-level + method-level
|
|
8
|
+
* - Angular: environment.apiUrl from environments/environment.ts
|
|
9
|
+
* - Vue: axios.defaults.baseURL
|
|
10
|
+
* - Slim PHP: $app->group prefix + route path
|
|
11
|
+
* - HapiJS: explicit path (no composition needed)
|
|
12
|
+
*
|
|
13
|
+
* Normalizes: remove double slashes, ensure single leading slash.
|
|
14
|
+
*/
|
|
15
|
+
/**
|
|
16
|
+
* Compose a full URL from multiple path segments.
|
|
17
|
+
* Handles: double slashes, missing leading slashes, trailing slashes.
|
|
18
|
+
*/
|
|
19
|
+
export declare function composeUrl(...segments: (string | undefined)[]): string;
|
|
20
|
+
/**
|
|
21
|
+
* Normalize a path template: ensure leading slash, remove double slashes,
|
|
22
|
+
* standardize parameter syntax.
|
|
23
|
+
*/
|
|
24
|
+
export declare function normalizePath(path: string): string;
|
|
25
|
+
/**
|
|
26
|
+
* Convert framework-specific parameter syntax to OpenAPI-style {param}.
|
|
27
|
+
*
|
|
28
|
+
* Flask: <param>, <int:param> → {param}
|
|
29
|
+
* Express: :param → {param}
|
|
30
|
+
* Slim PHP: {param} (already correct)
|
|
31
|
+
* HapiJS: {param} (already correct)
|
|
32
|
+
* Spring: {param} (already correct)
|
|
33
|
+
*/
|
|
34
|
+
export declare function normalizePathParams(path: string): string;
|
|
35
|
+
/**
|
|
36
|
+
* Compose full URL for a specific framework's route.
|
|
37
|
+
*/
|
|
38
|
+
export declare function composeFrameworkUrl(framework: string, parts: {
|
|
39
|
+
baseUrl?: string;
|
|
40
|
+
classPrefix?: string;
|
|
41
|
+
mountPrefix?: string;
|
|
42
|
+
routePath: string;
|
|
43
|
+
}): string;
|
|
44
|
+
//# sourceMappingURL=baseUrlComposer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"baseUrlComposer.d.ts","sourceRoot":"","sources":["../../../../../src/pipeline/stages/ast/baseUrlComposer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH;;;GAGG;AACH,wBAAgB,UAAU,CAAC,GAAG,QAAQ,EAAE,CAAC,MAAM,GAAG,SAAS,CAAC,EAAE,GAAG,MAAM,CAStE;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAkBlD;AAED;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAQxD;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CACjC,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE;IACL,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;CACnB,GACA,MAAM,CAUR"}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Base URL composer (Feature 27, Sub-PR 9)
|
|
4
|
+
*
|
|
5
|
+
* Unified URL composition across all frameworks:
|
|
6
|
+
* - Flask: Blueprint url_prefix + route path
|
|
7
|
+
* - Express: app.use mount prefix + router path + route path
|
|
8
|
+
* - Spring: @RequestMapping class-level + method-level
|
|
9
|
+
* - Angular: environment.apiUrl from environments/environment.ts
|
|
10
|
+
* - Vue: axios.defaults.baseURL
|
|
11
|
+
* - Slim PHP: $app->group prefix + route path
|
|
12
|
+
* - HapiJS: explicit path (no composition needed)
|
|
13
|
+
*
|
|
14
|
+
* Normalizes: remove double slashes, ensure single leading slash.
|
|
15
|
+
*/
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
exports.composeUrl = composeUrl;
|
|
18
|
+
exports.normalizePath = normalizePath;
|
|
19
|
+
exports.normalizePathParams = normalizePathParams;
|
|
20
|
+
exports.composeFrameworkUrl = composeFrameworkUrl;
|
|
21
|
+
/**
|
|
22
|
+
* Compose a full URL from multiple path segments.
|
|
23
|
+
* Handles: double slashes, missing leading slashes, trailing slashes.
|
|
24
|
+
*/
|
|
25
|
+
function composeUrl(...segments) {
|
|
26
|
+
const parts = segments
|
|
27
|
+
.filter((s) => typeof s === 'string' && s.length > 0)
|
|
28
|
+
.map((s) => s.replace(/^\/+|\/+$/g, ''));
|
|
29
|
+
const joined = parts.join('/');
|
|
30
|
+
const normalized = '/' + joined.replace(/\/+/g, '/');
|
|
31
|
+
return normalized === '/' ? '/' : normalized.replace(/\/+$/, '');
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Normalize a path template: ensure leading slash, remove double slashes,
|
|
35
|
+
* standardize parameter syntax.
|
|
36
|
+
*/
|
|
37
|
+
function normalizePath(path) {
|
|
38
|
+
if (!path)
|
|
39
|
+
return '/';
|
|
40
|
+
// Ensure leading slash
|
|
41
|
+
let normalized = path.startsWith('/') ? path : '/' + path;
|
|
42
|
+
// Remove double slashes (but not from protocol like http://)
|
|
43
|
+
// First handle leading double slashes
|
|
44
|
+
normalized = normalized.replace(/^\/\/+/, '/');
|
|
45
|
+
// Then handle double slashes in the middle
|
|
46
|
+
normalized = normalized.replace(/([^:])\/\/+/g, '$1/');
|
|
47
|
+
// Remove trailing slash (unless it's just "/")
|
|
48
|
+
if (normalized.length > 1) {
|
|
49
|
+
normalized = normalized.replace(/\/+$/, '');
|
|
50
|
+
}
|
|
51
|
+
return normalized;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Convert framework-specific parameter syntax to OpenAPI-style {param}.
|
|
55
|
+
*
|
|
56
|
+
* Flask: <param>, <int:param> → {param}
|
|
57
|
+
* Express: :param → {param}
|
|
58
|
+
* Slim PHP: {param} (already correct)
|
|
59
|
+
* HapiJS: {param} (already correct)
|
|
60
|
+
* Spring: {param} (already correct)
|
|
61
|
+
*/
|
|
62
|
+
function normalizePathParams(path) {
|
|
63
|
+
// Flask/Python: <param> or <type:param>
|
|
64
|
+
let normalized = path.replace(/<(?:\w+:)?(\w+)>/g, '{$1}');
|
|
65
|
+
// Express: :param (but not :// from URLs)
|
|
66
|
+
normalized = normalized.replace(/(?<=\/):([\w]+)/g, '{$1}');
|
|
67
|
+
return normalized;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Compose full URL for a specific framework's route.
|
|
71
|
+
*/
|
|
72
|
+
function composeFrameworkUrl(framework, parts) {
|
|
73
|
+
const segments = [];
|
|
74
|
+
if (parts.baseUrl)
|
|
75
|
+
segments.push(parts.baseUrl);
|
|
76
|
+
if (parts.classPrefix)
|
|
77
|
+
segments.push(parts.classPrefix);
|
|
78
|
+
if (parts.mountPrefix)
|
|
79
|
+
segments.push(parts.mountPrefix);
|
|
80
|
+
segments.push(parts.routePath);
|
|
81
|
+
const raw = composeUrl(...segments);
|
|
82
|
+
return normalizePathParams(raw);
|
|
83
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cross-file resolution pass (Feature 27)
|
|
3
|
+
*
|
|
4
|
+
* Orchestrates all registered cross-file resolvers after the initial AST
|
|
5
|
+
* parsing pass. Each resolver enriches the CrossFileSymbolTable with
|
|
6
|
+
* framework-specific resolution data (Blueprint prefixes, Angular injection
|
|
7
|
+
* chains, DDD interface mappings, etc.).
|
|
8
|
+
*
|
|
9
|
+
* Resolvers are registered via `registerCrossFileResolver()` and discovered
|
|
10
|
+
* via `getCrossFileResolvers()`. Each resolver implements the `CrossFileResolver`
|
|
11
|
+
* interface and self-declares which API frameworks it applies to.
|
|
12
|
+
*/
|
|
13
|
+
import type { CrossFileResolver, CrossFileSymbolTable } from './types';
|
|
14
|
+
import type { DetectedApiFramework } from '../../../discovery/frameworkDetector';
|
|
15
|
+
/**
|
|
16
|
+
* Register a cross-file resolver. Resolvers are run in registration order.
|
|
17
|
+
*/
|
|
18
|
+
export declare function registerCrossFileResolver(resolver: CrossFileResolver): void;
|
|
19
|
+
/**
|
|
20
|
+
* Return all registered cross-file resolvers.
|
|
21
|
+
*/
|
|
22
|
+
export declare function getCrossFileResolvers(): readonly CrossFileResolver[];
|
|
23
|
+
/**
|
|
24
|
+
* Clear all registered resolvers (for testing).
|
|
25
|
+
*/
|
|
26
|
+
export declare function clearCrossFileResolvers(): void;
|
|
27
|
+
export interface CrossFileResolutionPassResult {
|
|
28
|
+
/** Per-resolver diagnostics */
|
|
29
|
+
resolverResults: Array<{
|
|
30
|
+
resolverName: string;
|
|
31
|
+
entriesAdded: number;
|
|
32
|
+
diagnostics: string[];
|
|
33
|
+
unresolvedRefs: Array<{
|
|
34
|
+
ref: string;
|
|
35
|
+
reason: string;
|
|
36
|
+
}>;
|
|
37
|
+
}>;
|
|
38
|
+
/** Total entries added across all resolvers */
|
|
39
|
+
totalEntriesAdded: number;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Run all applicable cross-file resolvers against the symbol table.
|
|
43
|
+
*
|
|
44
|
+
* Each resolver mutates the symbol table in place, adding router mounts,
|
|
45
|
+
* injection chains, interface implementations, and middleware inheritance data.
|
|
46
|
+
*
|
|
47
|
+
* @param symbolTable - The cross-file symbol table to enrich
|
|
48
|
+
* @param projectRoot - Project root directory
|
|
49
|
+
* @param apiFrameworks - Detected API frameworks
|
|
50
|
+
* @param allSourceFiles - All source file paths
|
|
51
|
+
* @returns Aggregated diagnostics from all resolvers
|
|
52
|
+
*/
|
|
53
|
+
export declare function runCrossFileResolution(symbolTable: CrossFileSymbolTable, projectRoot: string, apiFrameworks: DetectedApiFramework[], allSourceFiles: string[]): CrossFileResolutionPassResult;
|
|
54
|
+
//# sourceMappingURL=crossFileResolutionPass.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"crossFileResolutionPass.d.ts","sourceRoot":"","sources":["../../../../../src/pipeline/stages/ast/crossFileResolutionPass.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EACV,iBAAiB,EAGjB,oBAAoB,EACrB,MAAM,SAAS,CAAC;AACjB,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,sCAAsC,CAAC;AAMjF;;GAEG;AACH,wBAAgB,yBAAyB,CAAC,QAAQ,EAAE,iBAAiB,GAAG,IAAI,CAK3E;AAED;;GAEG;AACH,wBAAgB,qBAAqB,IAAI,SAAS,iBAAiB,EAAE,CAEpE;AAED;;GAEG;AACH,wBAAgB,uBAAuB,IAAI,IAAI,CAE9C;AAID,MAAM,WAAW,6BAA6B;IAC5C,+BAA+B;IAC/B,eAAe,EAAE,KAAK,CAAC;QACrB,YAAY,EAAE,MAAM,CAAC;QACrB,YAAY,EAAE,MAAM,CAAC;QACrB,WAAW,EAAE,MAAM,EAAE,CAAC;QACtB,cAAc,EAAE,KAAK,CAAC;YAAE,GAAG,EAAE,MAAM,CAAC;YAAC,MAAM,EAAE,MAAM,CAAA;SAAE,CAAC,CAAC;KACxD,CAAC,CAAC;IACH,+CAA+C;IAC/C,iBAAiB,EAAE,MAAM,CAAC;CAC3B;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,sBAAsB,CACpC,WAAW,EAAE,oBAAoB,EACjC,WAAW,EAAE,MAAM,EACnB,aAAa,EAAE,oBAAoB,EAAE,EACrC,cAAc,EAAE,MAAM,EAAE,GACvB,6BAA6B,CAoC/B"}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Cross-file resolution pass (Feature 27)
|
|
4
|
+
*
|
|
5
|
+
* Orchestrates all registered cross-file resolvers after the initial AST
|
|
6
|
+
* parsing pass. Each resolver enriches the CrossFileSymbolTable with
|
|
7
|
+
* framework-specific resolution data (Blueprint prefixes, Angular injection
|
|
8
|
+
* chains, DDD interface mappings, etc.).
|
|
9
|
+
*
|
|
10
|
+
* Resolvers are registered via `registerCrossFileResolver()` and discovered
|
|
11
|
+
* via `getCrossFileResolvers()`. Each resolver implements the `CrossFileResolver`
|
|
12
|
+
* interface and self-declares which API frameworks it applies to.
|
|
13
|
+
*/
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.registerCrossFileResolver = registerCrossFileResolver;
|
|
16
|
+
exports.getCrossFileResolvers = getCrossFileResolvers;
|
|
17
|
+
exports.clearCrossFileResolvers = clearCrossFileResolvers;
|
|
18
|
+
exports.runCrossFileResolution = runCrossFileResolution;
|
|
19
|
+
// ─── Resolver registry ────────────────────────────────────────────────────────
|
|
20
|
+
const resolverRegistry = [];
|
|
21
|
+
/**
|
|
22
|
+
* Register a cross-file resolver. Resolvers are run in registration order.
|
|
23
|
+
*/
|
|
24
|
+
function registerCrossFileResolver(resolver) {
|
|
25
|
+
// Avoid duplicate registrations
|
|
26
|
+
if (!resolverRegistry.some((r) => r.name === resolver.name)) {
|
|
27
|
+
resolverRegistry.push(resolver);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Return all registered cross-file resolvers.
|
|
32
|
+
*/
|
|
33
|
+
function getCrossFileResolvers() {
|
|
34
|
+
return resolverRegistry;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Clear all registered resolvers (for testing).
|
|
38
|
+
*/
|
|
39
|
+
function clearCrossFileResolvers() {
|
|
40
|
+
resolverRegistry.length = 0;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Run all applicable cross-file resolvers against the symbol table.
|
|
44
|
+
*
|
|
45
|
+
* Each resolver mutates the symbol table in place, adding router mounts,
|
|
46
|
+
* injection chains, interface implementations, and middleware inheritance data.
|
|
47
|
+
*
|
|
48
|
+
* @param symbolTable - The cross-file symbol table to enrich
|
|
49
|
+
* @param projectRoot - Project root directory
|
|
50
|
+
* @param apiFrameworks - Detected API frameworks
|
|
51
|
+
* @param allSourceFiles - All source file paths
|
|
52
|
+
* @returns Aggregated diagnostics from all resolvers
|
|
53
|
+
*/
|
|
54
|
+
function runCrossFileResolution(symbolTable, projectRoot, apiFrameworks, allSourceFiles) {
|
|
55
|
+
const ctx = {
|
|
56
|
+
symbolTable,
|
|
57
|
+
projectRoot,
|
|
58
|
+
apiFrameworks,
|
|
59
|
+
allSourceFiles,
|
|
60
|
+
};
|
|
61
|
+
const resolverResults = [];
|
|
62
|
+
let totalEntriesAdded = 0;
|
|
63
|
+
for (const resolver of resolverRegistry) {
|
|
64
|
+
// Only run resolvers that apply to the detected frameworks
|
|
65
|
+
if (!resolver.appliesTo(apiFrameworks))
|
|
66
|
+
continue;
|
|
67
|
+
try {
|
|
68
|
+
const result = resolver.resolve(ctx);
|
|
69
|
+
resolverResults.push({
|
|
70
|
+
resolverName: resolver.name,
|
|
71
|
+
entriesAdded: result.entriesAdded,
|
|
72
|
+
diagnostics: result.diagnostics,
|
|
73
|
+
unresolvedRefs: result.unresolvedRefs,
|
|
74
|
+
});
|
|
75
|
+
totalEntriesAdded += result.entriesAdded;
|
|
76
|
+
}
|
|
77
|
+
catch (err) {
|
|
78
|
+
// Never let a resolver crash the pipeline
|
|
79
|
+
resolverResults.push({
|
|
80
|
+
resolverName: resolver.name,
|
|
81
|
+
entriesAdded: 0,
|
|
82
|
+
diagnostics: [`resolver-error: ${err instanceof Error ? err.message : String(err)}`],
|
|
83
|
+
unresolvedRefs: [],
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
return { resolverResults, totalEntriesAdded };
|
|
88
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"crossFileResolver.d.ts","sourceRoot":"","sources":["../../../../../src/pipeline/stages/ast/crossFileResolver.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAuC,MAAM,uBAAuB,CAAC;AAChG,OAAO,KAAK,EAAE,oBAAoB,EAAuC,MAAM,SAAS,CAAC;AAGzF;;;;;GAKG;AACH,wBAAgB,yBAAyB,CACvC,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,aAAa,CAAC,EAClC,WAAW,EAAE,MAAM,GAClB,oBAAoB,
|
|
1
|
+
{"version":3,"file":"crossFileResolver.d.ts","sourceRoot":"","sources":["../../../../../src/pipeline/stages/ast/crossFileResolver.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAuC,MAAM,uBAAuB,CAAC;AAChG,OAAO,KAAK,EAAE,oBAAoB,EAAuC,MAAM,SAAS,CAAC;AAGzF;;;;;GAKG;AACH,wBAAgB,yBAAyB,CACvC,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,aAAa,CAAC,EAClC,WAAW,EAAE,MAAM,GAClB,oBAAoB,CAgEtB;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,CACpC,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,oBAAoB,GAC1B,MAAM,GAAG,SAAS,CA4BpB"}
|
|
@@ -63,7 +63,16 @@ function buildCrossFileSymbolTable(models, projectRoot) {
|
|
|
63
63
|
}
|
|
64
64
|
importGraph.set(filePath, resolvedPaths);
|
|
65
65
|
}
|
|
66
|
-
return {
|
|
66
|
+
return {
|
|
67
|
+
models,
|
|
68
|
+
exportedSymbols,
|
|
69
|
+
classes,
|
|
70
|
+
importGraph,
|
|
71
|
+
routerMounts: new Map(),
|
|
72
|
+
injectionChains: new Map(),
|
|
73
|
+
interfaceImplementations: new Map(),
|
|
74
|
+
middlewareInheritance: new Map(),
|
|
75
|
+
};
|
|
67
76
|
}
|
|
68
77
|
/**
|
|
69
78
|
* Resolve a symbol name using the cross-file symbol table.
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Optional auth unifier (Feature 27, Sub-PR 9)
|
|
3
|
+
*
|
|
4
|
+
* Normalizes all framework-specific auth classifications to a unified SecurityClassification.
|
|
5
|
+
* Maps framework-specific patterns:
|
|
6
|
+
* Flask @jwt_optional → { optional: true }
|
|
7
|
+
* Express auth.optional / credentialsRequired: false → { optional: true }
|
|
8
|
+
* HapiJS auth: { mode: 'try' } → { optional: true }
|
|
9
|
+
* Spring @PreAuthorize → { required: true }
|
|
10
|
+
* Angular route guard → depends on guard type
|
|
11
|
+
*/
|
|
12
|
+
import type { SecurityClassification } from '../../../ast/astTypes';
|
|
13
|
+
export interface AuthClassificationEntry {
|
|
14
|
+
framework: string;
|
|
15
|
+
sourcePattern: string;
|
|
16
|
+
classification: SecurityClassification;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Framework-specific auth pattern → unified SecurityClassification.
|
|
20
|
+
*/
|
|
21
|
+
export declare function unifyAuthClassification(framework: string, pattern: string): SecurityClassification | undefined;
|
|
22
|
+
/**
|
|
23
|
+
* Detect auth coverage gaps.
|
|
24
|
+
*/
|
|
25
|
+
export interface AuthCoverageGap {
|
|
26
|
+
type: 'missing-401-test' | 'missing-optional-dual-path';
|
|
27
|
+
endpointPath: string;
|
|
28
|
+
security: SecurityClassification;
|
|
29
|
+
sourceFile: string;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Analyze auth coverage gaps in endpoints vs tests.
|
|
33
|
+
*/
|
|
34
|
+
export declare function detectAuthCoverageGaps(endpoints: Array<{
|
|
35
|
+
path: string;
|
|
36
|
+
security?: SecurityClassification;
|
|
37
|
+
sourceFile: string;
|
|
38
|
+
}>, testAssertionPaths: Set<string>): AuthCoverageGap[];
|
|
39
|
+
//# sourceMappingURL=optionalAuthUnifier.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"optionalAuthUnifier.d.ts","sourceRoot":"","sources":["../../../../../src/pipeline/stages/ast/optionalAuthUnifier.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AAEpE,MAAM,WAAW,uBAAuB;IACtC,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;IACtB,cAAc,EAAE,sBAAsB,CAAC;CACxC;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CACrC,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,GACd,sBAAsB,GAAG,SAAS,CAwCpC;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,kBAAkB,GAAG,4BAA4B,CAAC;IACxD,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,sBAAsB,CAAC;IACjC,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CACpC,SAAS,EAAE,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,sBAAsB,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,CAAC,EACzF,kBAAkB,EAAE,GAAG,CAAC,MAAM,CAAC,GAC9B,eAAe,EAAE,CA0BnB"}
|