api-tests-coverage 1.0.16 → 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/index.html +1 -1
- package/dist/src/discovery/fileClassifier.d.ts.map +1 -1
- package/dist/src/discovery/fileClassifier.js +15 -16
- package/dist/src/discovery/projectDiscovery.d.ts.map +1 -1
- package/dist/src/discovery/projectDiscovery.js +4 -1
- 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.map +1 -1
- package/dist/src/languages/javascript/angularDetector.js +50 -17
- package/dist/src/languages/javascript/assertionResolver.js +6 -4
- package/dist/src/languages/javascript/hapiDetector.d.ts.map +1 -1
- package/dist/src/languages/javascript/hapiDetector.js +48 -5
- package/dist/src/languages/javascript/vueDetector.d.ts +2 -0
- package/dist/src/languages/javascript/vueDetector.d.ts.map +1 -1
- package/dist/src/languages/javascript/vueDetector.js +22 -0
- package/dist/src/languages/python/index.d.ts +1 -1
- package/dist/src/languages/python/index.d.ts.map +1 -1
- package/dist/src/languages/python/index.js +33 -3
- 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 +46 -2
- package/dist/src/pipeline/stages/ast/baseUrlComposer.d.ts.map +1 -1
- package/dist/src/pipeline/stages/ast/baseUrlComposer.js +18 -4
- package/dist/src/pipeline/stages/ast/crossFileResolver.js +29 -0
- 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 +3 -1
- package/dist/src/pipeline/stages/ast/optionalAuthUnifier.d.ts.map +1 -1
- package/dist/src/pipeline/stages/ast/optionalAuthUnifier.js +34 -14
- package/dist/src/pipeline/stages/ast/resolvers/angularInjectionResolver.d.ts.map +1 -1
- package/dist/src/pipeline/stages/ast/resolvers/angularInjectionResolver.js +22 -3
- package/dist/src/pipeline/stages/ast/resolvers/dddLayerResolver.d.ts.map +1 -1
- package/dist/src/pipeline/stages/ast/resolvers/dddLayerResolver.js +104 -28
- package/dist/src/pipeline/stages/ast/resolvers/mybatisResolver.d.ts.map +1 -1
- package/dist/src/pipeline/stages/ast/resolvers/mybatisResolver.js +56 -0
- package/dist/src/pipeline/stages/ast/resolvers/vuexActionResolver.d.ts.map +1 -1
- package/dist/src/pipeline/stages/ast/resolvers/vuexActionResolver.js +43 -18
- package/dist/src/pipeline/stages/ast/rulesEnforcer.d.ts.map +1 -1
- package/dist/src/pipeline/stages/ast/rulesEnforcer.js +336 -45
- 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 +36 -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
|
@@ -151,8 +151,13 @@ function hasPartialResolution(graph, pathNodeIds) {
|
|
|
151
151
|
/**
|
|
152
152
|
* Build a ConfidenceEvidence object from a coverage path in the graph.
|
|
153
153
|
* Inspects the nodes and their source stages to determine what evidence exists.
|
|
154
|
+
*
|
|
155
|
+
* Optional `iastConfirmed` and `dastConfirmed` flags allow the caller to
|
|
156
|
+
* inject runtime confirmation state that may not be discoverable by walking
|
|
157
|
+
* `pathNodeIds` alone (e.g. when IAST/DAST nodes are not directly on the
|
|
158
|
+
* endpoint→test path in the graph).
|
|
154
159
|
*/
|
|
155
|
-
function buildConfidenceEvidence(graph, pathNodeIds, isStaticOnlyMode) {
|
|
160
|
+
function buildConfidenceEvidence(graph, pathNodeIds, isStaticOnlyMode, iastConfirmed, dastConfirmed) {
|
|
156
161
|
var _a, _b;
|
|
157
162
|
const sourceStages = new Set();
|
|
158
163
|
let hasIastConfirmation = false;
|
|
@@ -187,8 +192,8 @@ function buildConfidenceEvidence(graph, pathNodeIds, isStaticOnlyMode) {
|
|
|
187
192
|
}
|
|
188
193
|
return {
|
|
189
194
|
sourceStages: Array.from(sourceStages),
|
|
190
|
-
hasIastConfirmation,
|
|
191
|
-
hasDastConfirmation,
|
|
195
|
+
hasIastConfirmation: hasIastConfirmation || (iastConfirmed !== null && iastConfirmed !== void 0 ? iastConfirmed : false),
|
|
196
|
+
hasDastConfirmation: hasDastConfirmation || (dastConfirmed !== null && dastConfirmed !== void 0 ? dastConfirmed : false),
|
|
192
197
|
hasAssertionConfirmation,
|
|
193
198
|
hasMockBoundary,
|
|
194
199
|
hasPartialResolution: hasPartial,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"graph.d.ts","sourceRoot":"","sources":["../../../src/pipeline/graph.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EACV,SAAS,EACT,SAAS,EACT,aAAa,EACb,aAAa,EACb,YAAY,EACZ,SAAS,EACV,MAAM,SAAS,CAAC;AAEjB,qBAAa,sBAAsB;IACjC,OAAO,CAAC,KAAK,CAAqC;IAClD,OAAO,CAAC,KAAK,CAAqC;IAIlD,OAAO,CAAC,IAAI,EAAE,SAAS,GAAG,IAAI;IAI9B,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS;IAI1C,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO;IAI5B,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO;
|
|
1
|
+
{"version":3,"file":"graph.d.ts","sourceRoot":"","sources":["../../../src/pipeline/graph.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EACV,SAAS,EACT,SAAS,EACT,aAAa,EACb,aAAa,EACb,YAAY,EACZ,SAAS,EACV,MAAM,SAAS,CAAC;AAEjB,qBAAa,sBAAsB;IACjC,OAAO,CAAC,KAAK,CAAqC;IAClD,OAAO,CAAC,KAAK,CAAqC;IAIlD,OAAO,CAAC,IAAI,EAAE,SAAS,GAAG,IAAI;IAI9B,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS;IAI1C,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO;IAI5B,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO;IAa/B,cAAc,CAAC,IAAI,EAAE,aAAa,GAAG,SAAS,EAAE;IAIhD,eAAe,CAAC,KAAK,EAAE,SAAS,GAAG,SAAS,EAAE;IAI9C,WAAW,IAAI,SAAS,EAAE;IAI1B,IAAI,SAAS,IAAI,MAAM,CAEtB;IAID,OAAO,CAAC,IAAI,EAAE,SAAS,GAAG,IAAI;IAI9B,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS;IAI1C,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO;IAI5B,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO;IAI/B,mDAAmD;IACnD,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,EAAE;IAIzC,8CAA8C;IAC9C,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,EAAE;IAIvC,sEAAsE;IACtE,eAAe,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,SAAS,EAAE;IAQ9D,wCAAwC;IACxC,cAAc,CAAC,IAAI,EAAE,aAAa,GAAG,SAAS,EAAE;IAIhD,WAAW,IAAI,SAAS,EAAE;IAI1B,IAAI,SAAS,IAAI,MAAM,CAEtB;IAID;;;OAGG;IACH,iBAAiB,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,aAAa,EAAE,GAAG,SAAS,EAAE;IA4B5E;;;OAGG;IACH,iBAAiB,CACf,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,aAAa,GACtB,OAAO;IAmCV;;;OAGG;IACH,KAAK,CAAC,KAAK,EAAE,sBAAsB,GAAG,YAAY,EAAE;IAwCpD,cAAc,IAAI;QAAE,KAAK,EAAE,SAAS,EAAE,CAAC;QAAC,KAAK,EAAE,SAAS,EAAE,CAAA;KAAE;IAO5D,MAAM,CAAC,gBAAgB,CAAC,IAAI,EAAE;QAAE,KAAK,EAAE,SAAS,EAAE,CAAC;QAAC,KAAK,EAAE,SAAS,EAAE,CAAA;KAAE,GAAG,sBAAsB;IAajG,KAAK,IAAI,IAAI;CAId"}
|
|
@@ -23,7 +23,16 @@ class CoverageKnowledgeGraph {
|
|
|
23
23
|
return this.nodes.has(id);
|
|
24
24
|
}
|
|
25
25
|
removeNode(id) {
|
|
26
|
-
|
|
26
|
+
const deleted = this.nodes.delete(id);
|
|
27
|
+
if (deleted) {
|
|
28
|
+
// Remove all edges that reference this node to avoid dangling edges
|
|
29
|
+
for (const [edgeId, edge] of this.edges) {
|
|
30
|
+
if (edge.sourceNodeId === id || edge.targetNodeId === id) {
|
|
31
|
+
this.edges.delete(edgeId);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
return deleted;
|
|
27
36
|
}
|
|
28
37
|
getNodesByType(type) {
|
|
29
38
|
return Array.from(this.nodes.values()).filter((n) => n.type === type);
|
|
@@ -112,9 +121,11 @@ class CoverageKnowledgeGraph {
|
|
|
112
121
|
while (queue.length > 0) {
|
|
113
122
|
const path = queue.shift();
|
|
114
123
|
const currentId = path[path.length - 1];
|
|
115
|
-
|
|
124
|
+
// Don't skip endId — we need to check every path that arrives at it
|
|
125
|
+
if (currentId !== endId && visited.has(currentId))
|
|
116
126
|
continue;
|
|
117
|
-
|
|
127
|
+
if (currentId !== endId)
|
|
128
|
+
visited.add(currentId);
|
|
118
129
|
if (currentId === endId) {
|
|
119
130
|
// Check interior nodes (not start or end)
|
|
120
131
|
for (let i = 1; i < path.length - 1; i++) {
|
|
@@ -122,7 +133,8 @@ class CoverageKnowledgeGraph {
|
|
|
122
133
|
if ((node === null || node === void 0 ? void 0 : node.type) === nodeType)
|
|
123
134
|
return true;
|
|
124
135
|
}
|
|
125
|
-
return false
|
|
136
|
+
// Don't return false here — other paths may still contain the node type
|
|
137
|
+
continue;
|
|
126
138
|
}
|
|
127
139
|
const outEdges = this.getEdgesFrom(currentId);
|
|
128
140
|
for (const edge of outEdges) {
|
|
@@ -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;AA2B9C,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;CAoNjE"}
|
|
@@ -53,6 +53,14 @@ const graphBuilder_1 = require("./graphBuilder");
|
|
|
53
53
|
const fileClassifier_1 = require("../../../discovery/fileClassifier");
|
|
54
54
|
const projectDiscovery_1 = require("../../../discovery/projectDiscovery");
|
|
55
55
|
const parserRegistry_1 = require("../../../ast/parserRegistry");
|
|
56
|
+
const rulesEnforcer_1 = require("./rulesEnforcer");
|
|
57
|
+
const optionalAuthUnifier_1 = require("./optionalAuthUnifier");
|
|
58
|
+
const expressRouterResolver_1 = require("./resolvers/expressRouterResolver");
|
|
59
|
+
const flaskBlueprintResolver_1 = require("./resolvers/flaskBlueprintResolver");
|
|
60
|
+
const angularInjectionResolver_1 = require("./resolvers/angularInjectionResolver");
|
|
61
|
+
const vuexActionResolver_1 = require("./resolvers/vuexActionResolver");
|
|
62
|
+
const mybatisResolver_1 = require("./resolvers/mybatisResolver");
|
|
63
|
+
const dddLayerResolver_1 = require("./resolvers/dddLayerResolver");
|
|
56
64
|
const fs = __importStar(require("fs"));
|
|
57
65
|
const path = __importStar(require("path"));
|
|
58
66
|
class AstStage {
|
|
@@ -71,7 +79,8 @@ class AstStage {
|
|
|
71
79
|
const scaOutput = context.stageOutputs.get('sca');
|
|
72
80
|
// Build analysis context
|
|
73
81
|
const analysisContext = (0, astAnalysisOrchestrator_1.buildAnalysisContext)(context.config.astConfig);
|
|
74
|
-
// Discover all files
|
|
82
|
+
// Discover all files — XML, GraphQL, and PHP files are included in serviceFiles
|
|
83
|
+
// via SERVICE_CODE_EXTS in fileClassifier.ts (RULE-SA05, SA06)
|
|
75
84
|
const artifacts = (0, projectDiscovery_1.discoverProject)({ rootDir: context.projectRoot });
|
|
76
85
|
const allSourceFiles = [
|
|
77
86
|
...artifacts.testFiles,
|
|
@@ -131,8 +140,33 @@ class AstStage {
|
|
|
131
140
|
}
|
|
132
141
|
// Phase 2: Build cross-file symbol table
|
|
133
142
|
const crossFileTable = (0, crossFileResolver_1.buildCrossFileSymbolTable)(models, context.projectRoot);
|
|
134
|
-
// Phase 2b:
|
|
143
|
+
// Phase 2b: Register and run cross-file resolvers (Feature 27)
|
|
144
|
+
// Clear any stale registrations from prior runs, then register all 6 resolvers
|
|
145
|
+
(0, crossFileResolutionPass_1.clearCrossFileResolvers)();
|
|
146
|
+
(0, crossFileResolutionPass_1.registerCrossFileResolver)(new expressRouterResolver_1.ExpressRouterResolver());
|
|
147
|
+
(0, crossFileResolutionPass_1.registerCrossFileResolver)(new flaskBlueprintResolver_1.FlaskBlueprintResolver());
|
|
148
|
+
(0, crossFileResolutionPass_1.registerCrossFileResolver)(new angularInjectionResolver_1.AngularInjectionResolver());
|
|
149
|
+
(0, crossFileResolutionPass_1.registerCrossFileResolver)(new vuexActionResolver_1.VuexActionResolver());
|
|
150
|
+
(0, crossFileResolutionPass_1.registerCrossFileResolver)(new mybatisResolver_1.MyBatisResolver());
|
|
151
|
+
(0, crossFileResolutionPass_1.registerCrossFileResolver)(new dddLayerResolver_1.DddLayerResolver());
|
|
135
152
|
const crossFileResolutionResult = (0, crossFileResolutionPass_1.runCrossFileResolution)(crossFileTable, context.projectRoot, artifacts.apiFrameworks, allSourceFiles);
|
|
153
|
+
// Phase 2c: Detect auth coverage gaps (Feature 27)
|
|
154
|
+
// Collect all endpoints with their security classifications for gap analysis
|
|
155
|
+
const endpointsForAuthGaps = [];
|
|
156
|
+
for (const [filePath, model] of crossFileTable.models) {
|
|
157
|
+
if (!model.routeRegistrations)
|
|
158
|
+
continue;
|
|
159
|
+
for (const reg of model.routeRegistrations) {
|
|
160
|
+
endpointsForAuthGaps.push({
|
|
161
|
+
path: reg.path,
|
|
162
|
+
security: reg.security,
|
|
163
|
+
sourceFile: filePath,
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
const authCoverageGaps = (0, optionalAuthUnifier_1.detectAuthCoverageGaps)(endpointsForAuthGaps, new Set());
|
|
168
|
+
// Phase 2d: Enforce structure-agnostic rules (Feature 27)
|
|
169
|
+
const rulesResult = (0, rulesEnforcer_1.enforceStructureAgnosticRules)(crossFileTable, context.projectRoot);
|
|
136
170
|
// Phase 3: Run abstract layer traversal for test files
|
|
137
171
|
const traversalResults = new Map();
|
|
138
172
|
const depthCap = context.config.traversalDepthCap;
|
|
@@ -204,6 +238,10 @@ class AstStage {
|
|
|
204
238
|
graphEdgesAdded: edges.length,
|
|
205
239
|
crossFileResolversRun: crossFileResolutionResult.resolverResults.length,
|
|
206
240
|
crossFileEntriesAdded: crossFileResolutionResult.totalEntriesAdded,
|
|
241
|
+
rulesChecked: rulesResult.rulesChecked,
|
|
242
|
+
rulesPassed: rulesResult.rulesPassed,
|
|
243
|
+
ruleViolations: rulesResult.violations.length,
|
|
244
|
+
authCoverageGaps: authCoverageGaps.length,
|
|
207
245
|
},
|
|
208
246
|
};
|
|
209
247
|
context.diagnostics.set('ast', diagnostics);
|
|
@@ -238,7 +276,13 @@ function detectLanguage(filePath, scaOutput) {
|
|
|
238
276
|
'.kts': 'kotlin',
|
|
239
277
|
'.py': 'python',
|
|
240
278
|
'.rb': 'ruby',
|
|
279
|
+
'.php': 'php',
|
|
241
280
|
'.feature': 'cucumber',
|
|
242
281
|
};
|
|
282
|
+
// Handle GraphQL schema files and XML as special-case languages
|
|
283
|
+
if (ext === '.graphqls' || ext === '.graphql')
|
|
284
|
+
return 'graphql';
|
|
285
|
+
if (ext === '.xml')
|
|
286
|
+
return 'xml';
|
|
243
287
|
return extensionMap[ext];
|
|
244
288
|
}
|
|
@@ -1 +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,
|
|
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,CAyBtE;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"}
|
|
@@ -24,10 +24,24 @@ exports.composeFrameworkUrl = composeFrameworkUrl;
|
|
|
24
24
|
*/
|
|
25
25
|
function composeUrl(...segments) {
|
|
26
26
|
const parts = segments
|
|
27
|
-
.filter((s) => typeof s === 'string' && s.length > 0)
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
27
|
+
.filter((s) => typeof s === 'string' && s.length > 0);
|
|
28
|
+
if (parts.length === 0)
|
|
29
|
+
return '/';
|
|
30
|
+
// Detect protocol in the first segment (e.g. http://, https://)
|
|
31
|
+
const protocolMatch = parts[0].match(/^(\w+:\/\/)/);
|
|
32
|
+
let protocol = '';
|
|
33
|
+
if (protocolMatch) {
|
|
34
|
+
protocol = protocolMatch[1];
|
|
35
|
+
parts[0] = parts[0].slice(protocol.length);
|
|
36
|
+
}
|
|
37
|
+
const stripped = parts.map((s) => s.replace(/^\/+|\/+$/g, ''));
|
|
38
|
+
const joined = stripped.join('/');
|
|
39
|
+
const deduped = joined.replace(/\/+/g, '/');
|
|
40
|
+
if (protocol) {
|
|
41
|
+
const normalized = protocol + deduped;
|
|
42
|
+
return normalized.replace(/\/+$/, '') || protocol;
|
|
43
|
+
}
|
|
44
|
+
const normalized = '/' + deduped;
|
|
31
45
|
return normalized === '/' ? '/' : normalized.replace(/\/+$/, '');
|
|
32
46
|
}
|
|
33
47
|
/**
|
|
@@ -107,12 +107,31 @@ function resolveSymbolCrossFile(symbolName, fromFile, table) {
|
|
|
107
107
|
}
|
|
108
108
|
return undefined;
|
|
109
109
|
}
|
|
110
|
+
/** Built-in objects that should never be treated as import module names */
|
|
111
|
+
const BUILTIN_OBJECTS = new Set([
|
|
112
|
+
'console', 'math', 'json', 'object', 'array', 'promise', 'date',
|
|
113
|
+
'string', 'number', 'boolean', 'symbol', 'regexp', 'error', 'map',
|
|
114
|
+
'set', 'weakmap', 'weakset', 'proxy', 'reflect', 'intl',
|
|
115
|
+
'arraybuffer', 'sharedarraybuffer', 'atomics', 'dataview',
|
|
116
|
+
'this', 'self', 'super', 'window', 'document', 'process',
|
|
117
|
+
'global', 'globalthis', 'module', 'exports', 'require',
|
|
118
|
+
'__dirname', '__filename',
|
|
119
|
+
]);
|
|
110
120
|
/**
|
|
111
121
|
* Extract import declarations from a semantic model.
|
|
112
122
|
* This is a heuristic extraction — real import extraction would come from the AST.
|
|
113
123
|
*/
|
|
114
124
|
function extractImportsFromModel(filePath, model, projectRoot) {
|
|
115
125
|
const imports = [];
|
|
126
|
+
// Build a set of known identifiers from the model (constants and local variables)
|
|
127
|
+
// These are the names that could plausibly be import aliases
|
|
128
|
+
const knownIdentifiers = new Set();
|
|
129
|
+
for (const [name] of model.constants) {
|
|
130
|
+
knownIdentifiers.add(name);
|
|
131
|
+
}
|
|
132
|
+
for (const [name] of model.localVariables) {
|
|
133
|
+
knownIdentifiers.add(name);
|
|
134
|
+
}
|
|
116
135
|
// Use functions' calledFunctions to infer cross-file references
|
|
117
136
|
for (const [, func] of model.functions) {
|
|
118
137
|
for (const calledName of func.calledFunctions) {
|
|
@@ -120,6 +139,16 @@ function extractImportsFromModel(filePath, model, projectRoot) {
|
|
|
120
139
|
const dotIndex = calledName.indexOf('.');
|
|
121
140
|
if (dotIndex > 0) {
|
|
122
141
|
const modulePart = calledName.substring(0, dotIndex);
|
|
142
|
+
// Skip common built-in objects that are never import sources
|
|
143
|
+
if (BUILTIN_OBJECTS.has(modulePart.toLowerCase())) {
|
|
144
|
+
continue;
|
|
145
|
+
}
|
|
146
|
+
// Only treat as an import if the prefix matches a known identifier
|
|
147
|
+
// (constant or local variable) in this file, which is how import
|
|
148
|
+
// aliases typically appear in the semantic model
|
|
149
|
+
if (!knownIdentifiers.has(modulePart)) {
|
|
150
|
+
continue;
|
|
151
|
+
}
|
|
123
152
|
const resolvedPath = (0, importResolver_1.resolveImportPath)(`./${modulePart}`, filePath, projectRoot, model.language);
|
|
124
153
|
if (resolvedPath) {
|
|
125
154
|
imports.push({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"graphBuilder.d.ts","sourceRoot":"","sources":["../../../../../src/pipeline/stages/ast/graphBuilder.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAoB,uBAAuB,EAAE,MAAM,uBAAuB,CAAC;AACtG,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,
|
|
1
|
+
{"version":3,"file":"graphBuilder.d.ts","sourceRoot":"","sources":["../../../../../src/pipeline/stages/ast/graphBuilder.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAoB,uBAAuB,EAAE,MAAM,uBAAuB,CAAC;AACtG,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAiB,MAAM,aAAa,CAAC;AACvE,OAAO,KAAK,EAAE,oBAAoB,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAIrE;;GAEG;AACH,wBAAgB,aAAa,CAC3B,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,aAAa,CAAC,EAClC,cAAc,EAAE,oBAAoB,EACpC,gBAAgB,EAAE,GAAG,CAAC,MAAM,EAAE,eAAe,CAAC,EAC9C,YAAY,EAAE,GAAG,CAAC,MAAM,EAAE,uBAAuB,EAAE,CAAC,GACnD;IAAE,KAAK,EAAE,SAAS,EAAE,CAAC;IAAC,KAAK,EAAE,SAAS,EAAE,CAAA;CAAE,CA4S5C"}
|
|
@@ -60,6 +60,28 @@ function buildAstGraph(models, crossFileTable, traversalResults, interactions) {
|
|
|
60
60
|
addedEdgeIds.add(edge.id);
|
|
61
61
|
edges.push(edge);
|
|
62
62
|
}
|
|
63
|
+
/**
|
|
64
|
+
* Ensure a node exists in the graph. If the node ID is not yet present,
|
|
65
|
+
* create a stub node flagged as cross-file-unresolved (spec §2.3).
|
|
66
|
+
* Confidence on stub nodes is capped at 'low'.
|
|
67
|
+
*/
|
|
68
|
+
function ensureNodeExists(nodeId, missingFilePath, nodeType) {
|
|
69
|
+
if (addedNodeIds.has(nodeId))
|
|
70
|
+
return nodeId;
|
|
71
|
+
addNode({
|
|
72
|
+
id: nodeId,
|
|
73
|
+
type: nodeType,
|
|
74
|
+
label: `[unresolved] ${path.basename(missingFilePath)}`,
|
|
75
|
+
sourceStage: 'ast',
|
|
76
|
+
filePath: missingFilePath,
|
|
77
|
+
metadata: {
|
|
78
|
+
resolution: 'cross-file-unresolved',
|
|
79
|
+
confidence: 'low',
|
|
80
|
+
diagnostic: `Cross-file resolution failed: file "${missingFilePath}" was not found in parsed models`,
|
|
81
|
+
},
|
|
82
|
+
});
|
|
83
|
+
return nodeId;
|
|
84
|
+
}
|
|
63
85
|
// 1. Create file nodes for every parsed file
|
|
64
86
|
for (const [filePath, model] of models) {
|
|
65
87
|
const basename = path.basename(filePath);
|
|
@@ -241,6 +263,65 @@ function buildAstGraph(models, crossFileTable, traversalResults, interactions) {
|
|
|
241
263
|
});
|
|
242
264
|
}
|
|
243
265
|
}
|
|
266
|
+
// 7. Feature 27: Create router mount edges
|
|
267
|
+
for (const [filePath, mounts] of crossFileTable.routerMounts) {
|
|
268
|
+
const sourceId = `file:${filePath}`;
|
|
269
|
+
if (!addedNodeIds.has(sourceId))
|
|
270
|
+
continue;
|
|
271
|
+
for (const mount of mounts) {
|
|
272
|
+
const targetId = `file:${mount.targetModulePath}`;
|
|
273
|
+
// Create edge even if target not parsed (creates stub node for missing files)
|
|
274
|
+
addEdge({
|
|
275
|
+
id: `${sourceId}->mounts->${mount.prefix}:${mount.targetModulePath}`,
|
|
276
|
+
type: 'router-mount',
|
|
277
|
+
sourceNodeId: sourceId,
|
|
278
|
+
targetNodeId: ensureNodeExists(targetId, mount.targetModulePath, 'file'),
|
|
279
|
+
sourceStage: 'ast',
|
|
280
|
+
metadata: {
|
|
281
|
+
prefix: mount.prefix,
|
|
282
|
+
targetModule: mount.targetModulePath,
|
|
283
|
+
middlewareCount: mount.middleware.length,
|
|
284
|
+
},
|
|
285
|
+
});
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
// 8. Feature 27: Create injection chain edges
|
|
289
|
+
for (const [consumerFile, chains] of crossFileTable.injectionChains) {
|
|
290
|
+
for (const chain of chains) {
|
|
291
|
+
const consumerNodeId = `file:${chain.consumerFile}`;
|
|
292
|
+
const serviceNodeId = `file:${chain.serviceFile}`;
|
|
293
|
+
addEdge({
|
|
294
|
+
id: `${consumerNodeId}->injects->${chain.serviceClass}:${chain.serviceFile}`,
|
|
295
|
+
type: 'injects',
|
|
296
|
+
sourceNodeId: ensureNodeExists(consumerNodeId, chain.consumerFile, 'file'),
|
|
297
|
+
targetNodeId: ensureNodeExists(serviceNodeId, chain.serviceFile, 'file'),
|
|
298
|
+
sourceStage: 'ast',
|
|
299
|
+
metadata: {
|
|
300
|
+
consumerClass: chain.consumerClass,
|
|
301
|
+
serviceClass: chain.serviceClass,
|
|
302
|
+
injectionStyle: chain.injectionStyle,
|
|
303
|
+
},
|
|
304
|
+
});
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
// 9. Feature 27: Create interface implementation edges
|
|
308
|
+
for (const [ifaceFile, impls] of crossFileTable.interfaceImplementations) {
|
|
309
|
+
for (const impl of impls) {
|
|
310
|
+
const ifaceNodeId = `file:${impl.interfaceFile}`;
|
|
311
|
+
const implNodeId = `file:${impl.implFile}`;
|
|
312
|
+
addEdge({
|
|
313
|
+
id: `${implNodeId}->implements->${impl.interfaceName}:${impl.interfaceFile}`,
|
|
314
|
+
type: 'implements',
|
|
315
|
+
sourceNodeId: ensureNodeExists(implNodeId, impl.implFile, 'file'),
|
|
316
|
+
targetNodeId: ensureNodeExists(ifaceNodeId, impl.interfaceFile, 'file'),
|
|
317
|
+
sourceStage: 'ast',
|
|
318
|
+
metadata: {
|
|
319
|
+
interfaceName: impl.interfaceName,
|
|
320
|
+
implName: impl.implName,
|
|
321
|
+
},
|
|
322
|
+
});
|
|
323
|
+
}
|
|
324
|
+
}
|
|
244
325
|
return { nodes, edges };
|
|
245
326
|
}
|
|
246
327
|
/**
|
|
@@ -7,7 +7,9 @@
|
|
|
7
7
|
* Express auth.optional / credentialsRequired: false → { optional: true }
|
|
8
8
|
* HapiJS auth: { mode: 'try' } → { optional: true }
|
|
9
9
|
* Spring @PreAuthorize → { required: true }
|
|
10
|
-
*
|
|
10
|
+
* Slim PHP optionalAuth → { optional: true }, jwt/auth → { required: true }
|
|
11
|
+
* Angular canActivate:none → { optional: true } (interceptor-based)
|
|
12
|
+
* NestJS @UseGuards → { required: true }
|
|
11
13
|
*/
|
|
12
14
|
import type { SecurityClassification } from '../../../ast/astTypes';
|
|
13
15
|
export interface AuthClassificationEntry {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"optionalAuthUnifier.d.ts","sourceRoot":"","sources":["../../../../../src/pipeline/stages/ast/optionalAuthUnifier.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"optionalAuthUnifier.d.ts","sourceRoot":"","sources":["../../../../../src/pipeline/stages/ast/optionalAuthUnifier.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;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,CA6DpC;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"}
|
|
@@ -8,7 +8,9 @@
|
|
|
8
8
|
* Express auth.optional / credentialsRequired: false → { optional: true }
|
|
9
9
|
* HapiJS auth: { mode: 'try' } → { optional: true }
|
|
10
10
|
* Spring @PreAuthorize → { required: true }
|
|
11
|
-
*
|
|
11
|
+
* Slim PHP optionalAuth → { optional: true }, jwt/auth → { required: true }
|
|
12
|
+
* Angular canActivate:none → { optional: true } (interceptor-based)
|
|
13
|
+
* NestJS @UseGuards → { required: true }
|
|
12
14
|
*/
|
|
13
15
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
14
16
|
exports.unifyAuthClassification = unifyAuthClassification;
|
|
@@ -18,36 +20,54 @@ exports.detectAuthCoverageGaps = detectAuthCoverageGaps;
|
|
|
18
20
|
*/
|
|
19
21
|
function unifyAuthClassification(framework, pattern) {
|
|
20
22
|
const key = `${framework}:${pattern}`.toLowerCase();
|
|
21
|
-
// Flask patterns
|
|
22
|
-
if (
|
|
23
|
+
// Flask patterns — use word-boundary regex to avoid matching e.g. "@jwt_required_custom"
|
|
24
|
+
if (/^flask:@?jwt_required\b/.test(key)) {
|
|
23
25
|
return { type: 'jwt', required: true, optional: false, sourcePattern: pattern };
|
|
24
26
|
}
|
|
25
|
-
if (
|
|
27
|
+
if (/^flask:@?jwt_optional\b/.test(key)) {
|
|
26
28
|
return { type: 'jwt', required: false, optional: true, sourcePattern: pattern };
|
|
27
29
|
}
|
|
28
|
-
if (
|
|
30
|
+
if (/^flask:@?login_required\b/.test(key)) {
|
|
29
31
|
return { type: 'session', required: true, optional: false, sourcePattern: pattern };
|
|
30
32
|
}
|
|
31
|
-
// Express patterns
|
|
32
|
-
if (
|
|
33
|
+
// Express patterns — use word-boundary regex for precise matching
|
|
34
|
+
if (/^express:auth\.required\b/.test(key) || /^express:credentialsrequired:\s*true\b/.test(key)) {
|
|
33
35
|
return { type: 'jwt', required: true, optional: false, sourcePattern: pattern };
|
|
34
36
|
}
|
|
35
|
-
if (
|
|
37
|
+
if (/^express:auth\.optional\b/.test(key) || /^express:credentialsrequired:\s*false\b/.test(key)) {
|
|
36
38
|
return { type: 'jwt', required: false, optional: true, sourcePattern: pattern };
|
|
37
39
|
}
|
|
38
|
-
if (
|
|
40
|
+
if (/^express:passport\.authenticate\b/.test(key)) {
|
|
39
41
|
return { type: 'jwt', required: true, optional: false, sourcePattern: pattern };
|
|
40
42
|
}
|
|
41
43
|
// HapiJS patterns (framework may be 'hapi' or 'hapijs')
|
|
42
|
-
const isHapi =
|
|
43
|
-
if (isHapi && key
|
|
44
|
+
const isHapi = /^hapi(?:js)?:/.test(key);
|
|
45
|
+
if (isHapi && /\bauth\b/.test(key) && /\bmode\b/.test(key) && (/\btry\b/.test(key) || /\boptional\b/.test(key))) {
|
|
44
46
|
return { type: 'jwt', required: false, optional: true, sourcePattern: pattern };
|
|
45
47
|
}
|
|
46
|
-
if (isHapi && key
|
|
48
|
+
if (isHapi && /\bauth\b/.test(key) && !/\bfalse\b/.test(key) && !/\btry\b/.test(key) && !/\boptional\b/.test(key)) {
|
|
47
49
|
return { type: 'jwt', required: true, optional: false, sourcePattern: pattern };
|
|
48
50
|
}
|
|
49
|
-
// Spring patterns
|
|
50
|
-
if (
|
|
51
|
+
// Spring patterns — include @RolesAllowed and @WithMockUser
|
|
52
|
+
if (/^spring:@?preauthorize\b/.test(key) || /^spring:@?secured\b/.test(key) || /^spring:@?rolesallowed\b/.test(key)) {
|
|
53
|
+
return { type: 'custom', required: true, optional: false, sourcePattern: pattern };
|
|
54
|
+
}
|
|
55
|
+
if (/^spring:@?withmockuser\b/.test(key)) {
|
|
56
|
+
return { type: 'custom', required: true, optional: false, sourcePattern: pattern };
|
|
57
|
+
}
|
|
58
|
+
// Slim PHP patterns — slim:optionalAuth is optional, slim:jwt or slim:auth is required
|
|
59
|
+
if (/^slim:optionalauth\b/.test(key)) {
|
|
60
|
+
return { type: 'jwt', required: false, optional: true, sourcePattern: pattern };
|
|
61
|
+
}
|
|
62
|
+
if (/^slim:(?:jwt|auth)\b/.test(key)) {
|
|
63
|
+
return { type: 'jwt', required: true, optional: false, sourcePattern: pattern };
|
|
64
|
+
}
|
|
65
|
+
// Angular patterns — canActivate:none (no guard) with interceptor tokens is optional
|
|
66
|
+
if (/^angular:canactivate:none\b/.test(key)) {
|
|
67
|
+
return { type: 'custom', required: false, optional: true, sourcePattern: pattern };
|
|
68
|
+
}
|
|
69
|
+
// NestJS patterns — @UseGuards is required auth
|
|
70
|
+
if (/^nestjs:@?useguards\b/.test(key)) {
|
|
51
71
|
return { type: 'custom', required: true, optional: false, sourcePattern: pattern };
|
|
52
72
|
}
|
|
53
73
|
return undefined;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"angularInjectionResolver.d.ts","sourceRoot":"","sources":["../../../../../../src/pipeline/stages/ast/resolvers/angularInjectionResolver.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EACV,iBAAiB,EACjB,0BAA0B,EAC1B,yBAAyB,EAC1B,MAAM,UAAU,CAAC;AAClB,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,yCAAyC,CAAC;AAEpF,qBAAa,wBAAyB,YAAW,iBAAiB;IAChE,QAAQ,CAAC,IAAI,uBAAuB;IAEpC,SAAS,CAAC,UAAU,EAAE,oBAAoB,EAAE,GAAG,OAAO;IAItD,OAAO,CAAC,GAAG,EAAE,0BAA0B,GAAG,yBAAyB;
|
|
1
|
+
{"version":3,"file":"angularInjectionResolver.d.ts","sourceRoot":"","sources":["../../../../../../src/pipeline/stages/ast/resolvers/angularInjectionResolver.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EACV,iBAAiB,EACjB,0BAA0B,EAC1B,yBAAyB,EAC1B,MAAM,UAAU,CAAC;AAClB,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,yCAAyC,CAAC;AAEpF,qBAAa,wBAAyB,YAAW,iBAAiB;IAChE,QAAQ,CAAC,IAAI,uBAAuB;IAEpC,SAAS,CAAC,UAAU,EAAE,oBAAoB,EAAE,GAAG,OAAO;IAItD,OAAO,CAAC,GAAG,EAAE,0BAA0B,GAAG,yBAAyB;CAyCpE"}
|
|
@@ -24,9 +24,7 @@ class AngularInjectionResolver {
|
|
|
24
24
|
const unresolvedRefs = [];
|
|
25
25
|
// Build injection chains from class registry
|
|
26
26
|
for (const [className, classInfo] of ctx.symbolTable.classes) {
|
|
27
|
-
//
|
|
28
|
-
if (!classInfo.implementsInterfaces)
|
|
29
|
-
continue;
|
|
27
|
+
// Check any class that has a model — Angular services typically don't implement interfaces
|
|
30
28
|
// Look for classes that have methods making HTTP calls
|
|
31
29
|
const model = ctx.symbolTable.models.get(classInfo.filePath);
|
|
32
30
|
if (!model)
|
|
@@ -73,5 +71,26 @@ function findConsumers(serviceName, ctx) {
|
|
|
73
71
|
}
|
|
74
72
|
}
|
|
75
73
|
}
|
|
74
|
+
// Fallback: search class registry for classes that might inject this service
|
|
75
|
+
// (constructor injection detected by parameter name matching)
|
|
76
|
+
for (const [className, classInfo] of ctx.symbolTable.classes) {
|
|
77
|
+
// Skip if already found as a consumer
|
|
78
|
+
if (consumers.some((c) => c.className === className && c.file === classInfo.filePath))
|
|
79
|
+
continue;
|
|
80
|
+
// Check if this class's model has the service name in its calledFunctions
|
|
81
|
+
const model = ctx.symbolTable.models.get(classInfo.filePath);
|
|
82
|
+
if (!model)
|
|
83
|
+
continue;
|
|
84
|
+
for (const [, func] of model.functions) {
|
|
85
|
+
if (func.calledFunctions.some((f) => f.includes(serviceName))) {
|
|
86
|
+
consumers.push({
|
|
87
|
+
className,
|
|
88
|
+
file: classInfo.filePath,
|
|
89
|
+
style: 'constructor',
|
|
90
|
+
});
|
|
91
|
+
break;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
76
95
|
return consumers;
|
|
77
96
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dddLayerResolver.d.ts","sourceRoot":"","sources":["../../../../../../src/pipeline/stages/ast/resolvers/dddLayerResolver.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EACV,iBAAiB,EACjB,0BAA0B,EAC1B,yBAAyB,EAC1B,MAAM,UAAU,CAAC;AAClB,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,yCAAyC,CAAC;AAEpF,MAAM,WAAW,sBAAsB;IACrC,aAAa,EAAE,MAAM,CAAC;IACtB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,cAAc;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,SAAS,GAAG,OAAO,GAAG,OAAO,CAAC;IAC3C,gBAAgB,EAAE,MAAM,CAAC;IACzB,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,qBAAa,gBAAiB,YAAW,iBAAiB;IACxD,QAAQ,CAAC,IAAI,eAAe;IAE5B,SAAS,CAAC,UAAU,EAAE,oBAAoB,EAAE,GAAG,OAAO;IAMtD,OAAO,CAAC,GAAG,EAAE,0BAA0B,GAAG,yBAAyB;
|
|
1
|
+
{"version":3,"file":"dddLayerResolver.d.ts","sourceRoot":"","sources":["../../../../../../src/pipeline/stages/ast/resolvers/dddLayerResolver.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EACV,iBAAiB,EACjB,0BAA0B,EAC1B,yBAAyB,EAC1B,MAAM,UAAU,CAAC;AAClB,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,yCAAyC,CAAC;AAEpF,MAAM,WAAW,sBAAsB;IACrC,aAAa,EAAE,MAAM,CAAC;IACtB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,cAAc;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,SAAS,GAAG,OAAO,GAAG,OAAO,CAAC;IAC3C,gBAAgB,EAAE,MAAM,CAAC;IACzB,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,qBAAa,gBAAiB,YAAW,iBAAiB;IACxD,QAAQ,CAAC,IAAI,eAAe;IAE5B,SAAS,CAAC,UAAU,EAAE,oBAAoB,EAAE,GAAG,OAAO;IAMtD,OAAO,CAAC,GAAG,EAAE,0BAA0B,GAAG,yBAAyB;CA+JpE;AAED;;;GAGG;AACH,wBAAgB,0BAA0B,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,sBAAsB,EAAE,CAgFrG;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,cAAc,EAAE,CAiCrF;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,KAAK,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAcjG"}
|