api-tests-coverage 1.0.16 → 1.0.18
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-CYB1KXah.js +1 -0
- package/dist/dashboard/dist/assets/_baseUniq-Bwm426M6.js +1 -0
- package/dist/dashboard/dist/assets/arc-B7p8x22e.js +1 -0
- package/dist/dashboard/dist/assets/architectureDiagram-VXUJARFQ-wVr1_uNB.js +36 -0
- package/dist/dashboard/dist/assets/blockDiagram-VD42YOAC-BBXc88fn.js +122 -0
- package/dist/dashboard/dist/assets/c4Diagram-YG6GDRKO-BsgzPfQ3.js +10 -0
- package/dist/dashboard/dist/assets/channel-psxgcQ_j.js +1 -0
- package/dist/dashboard/dist/assets/chunk-4BX2VUAB-BF8loPLD.js +1 -0
- package/dist/dashboard/dist/assets/chunk-55IACEB6-C3HNF-UF.js +1 -0
- package/dist/dashboard/dist/assets/chunk-B4BG7PRW-wQ6TCEMq.js +165 -0
- package/dist/dashboard/dist/assets/chunk-DI55MBZ5-B7xHuqZu.js +220 -0
- package/dist/dashboard/dist/assets/chunk-FMBD7UC4-K3PC79JF.js +15 -0
- package/dist/dashboard/dist/assets/chunk-QN33PNHL-CmeZ1h1Z.js +1 -0
- package/dist/dashboard/dist/assets/chunk-QZHKN3VN-Cyg7Km90.js +1 -0
- package/dist/dashboard/dist/assets/chunk-TZMSLE5B-C8KNXDi7.js +1 -0
- package/dist/dashboard/dist/assets/classDiagram-2ON5EDUG-AMwn99HP.js +1 -0
- package/dist/dashboard/dist/assets/classDiagram-v2-WZHVMYZB-AMwn99HP.js +1 -0
- package/dist/dashboard/dist/assets/clone-KEkbvJY9.js +1 -0
- package/dist/dashboard/dist/assets/cose-bilkent-S5V4N54A-YL9kFxCl.js +1 -0
- package/dist/dashboard/dist/assets/dagre-6UL2VRFP-NZWnQN_Y.js +4 -0
- package/dist/dashboard/dist/assets/diagram-PSM6KHXK-DGtyS7lD.js +24 -0
- package/dist/dashboard/dist/assets/diagram-QEK2KX5R-CSCGZUfr.js +43 -0
- package/dist/dashboard/dist/assets/diagram-S2PKOQOG-DdqZVGN1.js +24 -0
- package/dist/dashboard/dist/assets/erDiagram-Q2GNP2WA-Dhb_VQMS.js +60 -0
- package/dist/dashboard/dist/assets/flowDiagram-NV44I4VS-gKUH-GJ2.js +162 -0
- package/dist/dashboard/dist/assets/ganttDiagram-JELNMOA3-Dm_lLo9y.js +267 -0
- package/dist/dashboard/dist/assets/gitGraphDiagram-V2S2FVAM-DM9AW1aP.js +65 -0
- package/dist/dashboard/dist/assets/graph-Clj85F2M.js +1 -0
- package/dist/dashboard/dist/assets/index-CqEIqNus.js +781 -0
- package/dist/dashboard/dist/assets/index-xecKLQ58.css +1 -0
- package/dist/dashboard/dist/assets/infoDiagram-HS3SLOUP-BMp4C5wf.js +2 -0
- package/dist/dashboard/dist/assets/journeyDiagram-XKPGCS4Q-BC0GSZ7W.js +139 -0
- package/dist/dashboard/dist/assets/kanban-definition-3W4ZIXB7-D6aRd_q1.js +89 -0
- package/dist/dashboard/dist/assets/layout-BbJNDkTr.js +1 -0
- package/dist/dashboard/dist/assets/mindmap-definition-VGOIOE7T-B93XW27v.js +68 -0
- package/dist/dashboard/dist/assets/pieDiagram-ADFJNKIX-9G1tEuaq.js +30 -0
- package/dist/dashboard/dist/assets/quadrantDiagram-AYHSOK5B-jDtdB4Ws.js +7 -0
- package/dist/dashboard/dist/assets/requirementDiagram-UZGBJVZJ-WIJ0qiJG.js +64 -0
- package/dist/dashboard/dist/assets/sankeyDiagram-TZEHDZUN-Cb4WB9UB.js +10 -0
- package/dist/dashboard/dist/assets/sequenceDiagram-WL72ISMW-BqGJWVUS.js +145 -0
- package/dist/dashboard/dist/assets/stateDiagram-FKZM4ZOC-0Wd-KmOv.js +1 -0
- package/dist/dashboard/dist/assets/stateDiagram-v2-4FDKWEC3-BlwaoFEG.js +1 -0
- package/dist/dashboard/dist/assets/timeline-definition-IT6M3QCI-CAmQOjBu.js +61 -0
- package/dist/dashboard/dist/assets/treemap-GDKQZRPO-CRP-WvE-.js +162 -0
- package/dist/dashboard/dist/assets/xychartDiagram-PRI3JC2R-5DoR2_q5.js +7 -0
- package/dist/dashboard/dist/index.html +2 -2
- package/dist/src/config/defaultConfig.d.ts.map +1 -1
- package/dist/src/config/defaultConfig.js +37 -0
- package/dist/src/config/types.d.ts +42 -0
- package/dist/src/config/types.d.ts.map +1 -1
- package/dist/src/config/validateConfig.d.ts.map +1 -1
- package/dist/src/config/validateConfig.js +3 -0
- 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/generation/ai-flow-exporter.d.ts +7 -0
- package/dist/src/generation/ai-flow-exporter.d.ts.map +1 -0
- package/dist/src/generation/ai-flow-exporter.js +260 -0
- package/dist/src/generation/context-builder.d.ts +16 -0
- package/dist/src/generation/context-builder.d.ts.map +1 -0
- package/dist/src/generation/context-builder.js +170 -0
- package/dist/src/generation/engine.d.ts +19 -0
- package/dist/src/generation/engine.d.ts.map +1 -0
- package/dist/src/generation/engine.js +204 -0
- package/dist/src/generation/file-router.d.ts +8 -0
- package/dist/src/generation/file-router.d.ts.map +1 -0
- package/dist/src/generation/file-router.js +98 -0
- package/dist/src/generation/gap-extractor.d.ts +7 -0
- package/dist/src/generation/gap-extractor.d.ts.map +1 -0
- package/dist/src/generation/gap-extractor.js +291 -0
- package/dist/src/generation/index.d.ts +9 -0
- package/dist/src/generation/index.d.ts.map +1 -0
- package/dist/src/generation/index.js +15 -0
- package/dist/src/generation/quality-scorer.d.ts +15 -0
- package/dist/src/generation/quality-scorer.d.ts.map +1 -0
- package/dist/src/generation/quality-scorer.js +273 -0
- package/dist/src/generation/template-renderer.d.ts +12 -0
- package/dist/src/generation/template-renderer.d.ts.map +1 -0
- package/dist/src/generation/template-renderer.js +546 -0
- package/dist/src/generation/types.d.ts +269 -0
- package/dist/src/generation/types.d.ts.map +1 -0
- package/dist/src/generation/types.js +6 -0
- package/dist/src/index.js +113 -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.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
|
@@ -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"}
|
|
@@ -28,23 +28,80 @@ class DddLayerResolver {
|
|
|
28
28
|
const repoInterfaces = [];
|
|
29
29
|
const cqrsHandlers = [];
|
|
30
30
|
const implementations = new Map();
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
31
|
+
// ----- Detect from class registry and semantic models -----
|
|
32
|
+
// 1. Detect repository interfaces from class registry
|
|
33
|
+
for (const [className, classDecl] of ctx.symbolTable.classes) {
|
|
34
|
+
const isRepoByName = /(?:Repository|Repo|Store|Gateway)$/.test(className);
|
|
35
|
+
const repoMethods = classDecl.methods.filter(m => /^(?:findBy\w+|find\w+|save|saveAll|delete|deleteById|existsBy\w+|countBy\w+|getBy\w+)$/.test(m));
|
|
36
|
+
if (isRepoByName && repoMethods.length > 0) {
|
|
37
|
+
repoInterfaces.push({
|
|
38
|
+
interfaceName: className,
|
|
39
|
+
methods: repoMethods,
|
|
40
|
+
sourceFile: classDecl.filePath,
|
|
41
|
+
line: classDecl.line,
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
else if (!isRepoByName && repoMethods.length >= 2) {
|
|
45
|
+
// Generic interface with enough repository-like methods
|
|
46
|
+
repoInterfaces.push({
|
|
47
|
+
interfaceName: className,
|
|
48
|
+
methods: repoMethods,
|
|
49
|
+
sourceFile: classDecl.filePath,
|
|
50
|
+
line: classDecl.line,
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
// 2. Detect CQRS handlers from class registry + semantic models
|
|
55
|
+
for (const [className, classDecl] of ctx.symbolTable.classes) {
|
|
56
|
+
const model = ctx.symbolTable.models.get(classDecl.filePath);
|
|
57
|
+
if (!model)
|
|
58
|
+
continue;
|
|
59
|
+
for (const methodName of classDecl.methods) {
|
|
60
|
+
if (methodName !== 'execute' && methodName !== 'handle' && methodName !== 'apply')
|
|
61
|
+
continue;
|
|
62
|
+
// Determine handler type from class name or method context
|
|
63
|
+
let handlerType = 'command';
|
|
64
|
+
if (/Query/.test(className))
|
|
65
|
+
handlerType = 'query';
|
|
66
|
+
else if (/Event/.test(className))
|
|
67
|
+
handlerType = 'event';
|
|
68
|
+
// Try to get parameter type from the function's annotations or the class name
|
|
69
|
+
const func = model.functions.get(methodName);
|
|
70
|
+
let parameterType = `${className.replace(/Handler$/, '')}`;
|
|
71
|
+
if (func === null || func === void 0 ? void 0 : func.annotations) {
|
|
72
|
+
// Check for annotations that hint at the command/query type
|
|
73
|
+
for (const ann of func.annotations) {
|
|
74
|
+
const typeMatch = ann.match(/(\w+(?:Command|Query|Event))/);
|
|
75
|
+
if (typeMatch) {
|
|
76
|
+
parameterType = typeMatch[1];
|
|
77
|
+
if (/Command$/.test(parameterType))
|
|
78
|
+
handlerType = 'command';
|
|
79
|
+
else if (/Query$/.test(parameterType))
|
|
80
|
+
handlerType = 'query';
|
|
81
|
+
else if (/Event$/.test(parameterType))
|
|
82
|
+
handlerType = 'event';
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
cqrsHandlers.push({
|
|
87
|
+
className,
|
|
88
|
+
handlerType,
|
|
89
|
+
handleMethodName: methodName,
|
|
90
|
+
parameterType,
|
|
91
|
+
sourceFile: classDecl.filePath,
|
|
92
|
+
line: classDecl.line,
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
// 3. Detect implements clauses from class registry (already parsed by tree-sitter)
|
|
97
|
+
for (const [className, classDecl] of ctx.symbolTable.classes) {
|
|
98
|
+
if (!classDecl.implementsInterfaces || classDecl.implementsInterfaces.length === 0)
|
|
34
99
|
continue;
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
// Detect CQRS handlers
|
|
39
|
-
const handlers = detectCqrsHandlers(sourceText, filePath);
|
|
40
|
-
cqrsHandlers.push(...handlers);
|
|
41
|
-
// Detect implements clauses
|
|
42
|
-
const impls = detectImplementsClauses(sourceText, filePath);
|
|
43
|
-
for (const [ifaceName, implName] of impls) {
|
|
44
|
-
if (!implementations.has(ifaceName)) {
|
|
45
|
-
implementations.set(ifaceName, []);
|
|
100
|
+
for (const iface of classDecl.implementsInterfaces) {
|
|
101
|
+
if (!implementations.has(iface)) {
|
|
102
|
+
implementations.set(iface, []);
|
|
46
103
|
}
|
|
47
|
-
implementations.get(
|
|
104
|
+
implementations.get(iface).push(className);
|
|
48
105
|
}
|
|
49
106
|
}
|
|
50
107
|
// Map interface → implementation in symbolTable
|
|
@@ -72,6 +129,38 @@ class DddLayerResolver {
|
|
|
72
129
|
}
|
|
73
130
|
}
|
|
74
131
|
}
|
|
132
|
+
// Write repository interfaces into symbolTable (Section 5.3)
|
|
133
|
+
for (const repo of repoInterfaces) {
|
|
134
|
+
const key = repo.sourceFile;
|
|
135
|
+
if (!ctx.symbolTable.interfaceImplementations.has(key)) {
|
|
136
|
+
ctx.symbolTable.interfaceImplementations.set(key, []);
|
|
137
|
+
}
|
|
138
|
+
const existing = ctx.symbolTable.interfaceImplementations.get(key);
|
|
139
|
+
const alreadyMapped = existing.some(e => e.interfaceName === repo.interfaceName);
|
|
140
|
+
if (!alreadyMapped) {
|
|
141
|
+
existing.push({
|
|
142
|
+
interfaceName: repo.interfaceName,
|
|
143
|
+
interfaceFile: repo.sourceFile,
|
|
144
|
+
implName: '',
|
|
145
|
+
implFile: '',
|
|
146
|
+
});
|
|
147
|
+
entriesAdded++;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
// Write CQRS handlers as service-layer entries into symbolTable (Section 5.2)
|
|
151
|
+
for (const handler of cqrsHandlers) {
|
|
152
|
+
const key = handler.sourceFile;
|
|
153
|
+
if (!ctx.symbolTable.interfaceImplementations.has(key)) {
|
|
154
|
+
ctx.symbolTable.interfaceImplementations.set(key, []);
|
|
155
|
+
}
|
|
156
|
+
ctx.symbolTable.interfaceImplementations.get(key).push({
|
|
157
|
+
interfaceName: handler.parameterType,
|
|
158
|
+
interfaceFile: handler.sourceFile,
|
|
159
|
+
implName: handler.className,
|
|
160
|
+
implFile: handler.sourceFile,
|
|
161
|
+
});
|
|
162
|
+
entriesAdded++;
|
|
163
|
+
}
|
|
75
164
|
if (repoInterfaces.length > 0) {
|
|
76
165
|
diagnostics.push(`Found ${repoInterfaces.length} repository interface(s)`);
|
|
77
166
|
}
|
|
@@ -211,19 +300,6 @@ function detectImplementsClauses(source, filePath) {
|
|
|
211
300
|
}
|
|
212
301
|
return impls;
|
|
213
302
|
}
|
|
214
|
-
function getSourceText(filePath, ctx) {
|
|
215
|
-
// Try to get content from models (stored as raw source in semantic model)
|
|
216
|
-
// For now, we scan from the model's functions and other extracted data
|
|
217
|
-
// to detect patterns. In practice, we use regex on the raw source.
|
|
218
|
-
// If the model has functions, we have some content available.
|
|
219
|
-
const model = ctx.symbolTable.models.get(filePath);
|
|
220
|
-
if (!model)
|
|
221
|
-
return undefined;
|
|
222
|
-
// We return a synthetic source text reconstructed from available data.
|
|
223
|
-
// In a full implementation, we'd cache the raw source from the parse stage.
|
|
224
|
-
// For now, return undefined to indicate we can't access raw source from the symbol table.
|
|
225
|
-
return undefined;
|
|
226
|
-
}
|
|
227
303
|
function findFileForClass(className, ctx) {
|
|
228
304
|
// Search through exported symbols and class registry
|
|
229
305
|
const classInfo = ctx.symbolTable.classes.get(className);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mybatisResolver.d.ts","sourceRoot":"","sources":["../../../../../../src/pipeline/stages/ast/resolvers/mybatisResolver.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EACV,iBAAiB,EACjB,0BAA0B,EAC1B,yBAAyB,EAC1B,MAAM,UAAU,CAAC;AAClB,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,yCAAyC,CAAC;
|
|
1
|
+
{"version":3,"file":"mybatisResolver.d.ts","sourceRoot":"","sources":["../../../../../../src/pipeline/stages/ast/resolvers/mybatisResolver.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EACV,iBAAiB,EACjB,0BAA0B,EAC1B,yBAAyB,EAC1B,MAAM,UAAU,CAAC;AAClB,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,yCAAyC,CAAC;AAIpF,MAAM,WAAW,cAAc;IAC7B,0DAA0D;IAC1D,eAAe,EAAE,MAAM,CAAC;IACxB,8CAA8C;IAC9C,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,yDAAyD;IACzD,YAAY,EAAE,MAAM,CAAC;IACrB,0CAA0C;IAC1C,OAAO,EAAE,MAAM,CAAC;IAChB,iCAAiC;IACjC,UAAU,EAAE,MAAM,EAAE,CAAC;CACtB;AAED,qBAAa,eAAgB,YAAW,iBAAiB;IACvD,QAAQ,CAAC,IAAI,aAAa;IAE1B,SAAS,CAAC,UAAU,EAAE,oBAAoB,EAAE,GAAG,OAAO;IAItD,OAAO,CAAC,GAAG,EAAE,0BAA0B,GAAG,yBAAyB;CAmFpE"}
|
|
@@ -6,8 +6,43 @@
|
|
|
6
6
|
* - @Mapper interface FQCN ↔ <mapper namespace="..."> in XML
|
|
7
7
|
* - Interface method names ↔ <select id="...">, <insert id="...">, etc.
|
|
8
8
|
*/
|
|
9
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
12
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
13
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
14
|
+
}
|
|
15
|
+
Object.defineProperty(o, k2, desc);
|
|
16
|
+
}) : (function(o, m, k, k2) {
|
|
17
|
+
if (k2 === undefined) k2 = k;
|
|
18
|
+
o[k2] = m[k];
|
|
19
|
+
}));
|
|
20
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
21
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
22
|
+
}) : function(o, v) {
|
|
23
|
+
o["default"] = v;
|
|
24
|
+
});
|
|
25
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
26
|
+
var ownKeys = function(o) {
|
|
27
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
28
|
+
var ar = [];
|
|
29
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
30
|
+
return ar;
|
|
31
|
+
};
|
|
32
|
+
return ownKeys(o);
|
|
33
|
+
};
|
|
34
|
+
return function (mod) {
|
|
35
|
+
if (mod && mod.__esModule) return mod;
|
|
36
|
+
var result = {};
|
|
37
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
38
|
+
__setModuleDefault(result, mod);
|
|
39
|
+
return result;
|
|
40
|
+
};
|
|
41
|
+
})();
|
|
9
42
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
43
|
exports.MyBatisResolver = void 0;
|
|
44
|
+
const mybatisXmlParser_1 = require("../../../../languages/java/mybatisXmlParser");
|
|
45
|
+
const fs = __importStar(require("fs"));
|
|
11
46
|
class MyBatisResolver {
|
|
12
47
|
constructor() {
|
|
13
48
|
this.name = 'mybatis';
|
|
@@ -41,6 +76,27 @@ class MyBatisResolver {
|
|
|
41
76
|
mapperInterfaces.push({ name: className, file: classInfo.filePath });
|
|
42
77
|
}
|
|
43
78
|
}
|
|
79
|
+
// Parse XML mapper files from the project
|
|
80
|
+
for (const filePath of ctx.allSourceFiles) {
|
|
81
|
+
if (!filePath.endsWith('.xml'))
|
|
82
|
+
continue;
|
|
83
|
+
try {
|
|
84
|
+
const content = fs.readFileSync(filePath, 'utf-8');
|
|
85
|
+
if (!(0, mybatisXmlParser_1.isMyBatisMapperXml)(content))
|
|
86
|
+
continue;
|
|
87
|
+
const parsed = (0, mybatisXmlParser_1.parseMyBatisMapper)(content, filePath);
|
|
88
|
+
if (parsed) {
|
|
89
|
+
xmlMappers.push({
|
|
90
|
+
namespace: parsed.namespace,
|
|
91
|
+
file: filePath,
|
|
92
|
+
methods: parsed.queries.map((q) => q.id),
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
catch {
|
|
97
|
+
// Skip unreadable XML files
|
|
98
|
+
}
|
|
99
|
+
}
|
|
44
100
|
// Match mapper interfaces to XML files by namespace suffix
|
|
45
101
|
for (const xml of xmlMappers) {
|
|
46
102
|
const simpleName = (_b = xml.namespace.split('.').pop()) !== null && _b !== void 0 ? _b : xml.namespace;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vuexActionResolver.d.ts","sourceRoot":"","sources":["../../../../../../src/pipeline/stages/ast/resolvers/vuexActionResolver.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EACV,iBAAiB,EACjB,0BAA0B,EAC1B,yBAAyB,EAC1B,MAAM,UAAU,CAAC;AAClB,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,yCAAyC,CAAC;AAEpF,qBAAa,kBAAmB,YAAW,iBAAiB;IAC1D,QAAQ,CAAC,IAAI,iBAAiB;IAE9B,SAAS,CAAC,UAAU,EAAE,oBAAoB,EAAE,GAAG,OAAO;IAItD,OAAO,CAAC,GAAG,EAAE,0BAA0B,GAAG,yBAAyB;
|
|
1
|
+
{"version":3,"file":"vuexActionResolver.d.ts","sourceRoot":"","sources":["../../../../../../src/pipeline/stages/ast/resolvers/vuexActionResolver.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EACV,iBAAiB,EACjB,0BAA0B,EAC1B,yBAAyB,EAC1B,MAAM,UAAU,CAAC;AAClB,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,yCAAyC,CAAC;AAEpF,qBAAa,kBAAmB,YAAW,iBAAiB;IAC1D,QAAQ,CAAC,IAAI,iBAAiB;IAE9B,SAAS,CAAC,UAAU,EAAE,oBAAoB,EAAE,GAAG,OAAO;IAItD,OAAO,CAAC,GAAG,EAAE,0BAA0B,GAAG,yBAAyB;CAgEpE"}
|
|
@@ -21,33 +21,58 @@ class VuexActionResolver {
|
|
|
21
21
|
let entriesAdded = 0;
|
|
22
22
|
const diagnostics = [];
|
|
23
23
|
const unresolvedRefs = [];
|
|
24
|
-
//
|
|
25
|
-
|
|
26
|
-
let vuexStoreFiles = 0;
|
|
27
|
-
let dispatchFiles = 0;
|
|
24
|
+
// Collect Vuex store files: files with functions that have API calls (actions)
|
|
25
|
+
const actionFiles = new Map(); // filePath → action function names
|
|
28
26
|
for (const [filePath, model] of ctx.symbolTable.models) {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
for (const [, func] of model.functions) {
|
|
27
|
+
const actionNames = [];
|
|
28
|
+
for (const [funcName, func] of model.functions) {
|
|
32
29
|
if (func.bodyHttpCalls.length > 0) {
|
|
33
|
-
|
|
34
|
-
break;
|
|
30
|
+
actionNames.push(funcName);
|
|
35
31
|
}
|
|
36
32
|
}
|
|
37
|
-
if (
|
|
38
|
-
|
|
33
|
+
if (actionNames.length > 0) {
|
|
34
|
+
actionFiles.set(filePath, actionNames);
|
|
39
35
|
}
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
36
|
+
}
|
|
37
|
+
// Find dispatch calls and link them to actions
|
|
38
|
+
for (const [filePath, model] of ctx.symbolTable.models) {
|
|
39
|
+
for (const [funcName, func] of model.functions) {
|
|
40
|
+
for (const calledFunc of func.calledFunctions) {
|
|
41
|
+
if (!calledFunc.includes('dispatch'))
|
|
42
|
+
continue;
|
|
43
|
+
// Try to match dispatched action name to a known action function
|
|
44
|
+
// dispatch('getArticles') → match to 'getArticles' action in a store file
|
|
45
|
+
// Extract the action name from the dispatch call if possible
|
|
46
|
+
// Since we only have function names from calledFunctions, look for action names
|
|
47
|
+
// across all store files
|
|
48
|
+
for (const [storeFile, actionNames] of actionFiles) {
|
|
49
|
+
if (storeFile === filePath)
|
|
50
|
+
continue; // Don't link a file to itself
|
|
51
|
+
for (const actionName of actionNames) {
|
|
52
|
+
// Check if the current file references this action name
|
|
53
|
+
if (func.calledFunctions.some((f) => f.includes(actionName))) {
|
|
54
|
+
if (!ctx.symbolTable.injectionChains.has(filePath)) {
|
|
55
|
+
ctx.symbolTable.injectionChains.set(filePath, []);
|
|
56
|
+
}
|
|
57
|
+
ctx.symbolTable.injectionChains.get(filePath).push({
|
|
58
|
+
consumerFile: filePath,
|
|
59
|
+
consumerClass: funcName,
|
|
60
|
+
serviceClass: actionName,
|
|
61
|
+
serviceFile: storeFile,
|
|
62
|
+
injectionStyle: 'property',
|
|
63
|
+
});
|
|
64
|
+
entriesAdded++;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
45
67
|
}
|
|
46
68
|
}
|
|
47
69
|
}
|
|
48
70
|
}
|
|
49
|
-
if (
|
|
50
|
-
diagnostics.push(`Found ${
|
|
71
|
+
if (actionFiles.size > 0) {
|
|
72
|
+
diagnostics.push(`Found ${actionFiles.size} Vuex store file(s) with actions`);
|
|
73
|
+
}
|
|
74
|
+
if (entriesAdded > 0) {
|
|
75
|
+
diagnostics.push(`Linked ${entriesAdded} Vuex dispatch→action chain(s)`);
|
|
51
76
|
}
|
|
52
77
|
return { entriesAdded, diagnostics, unresolvedRefs };
|
|
53
78
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rulesEnforcer.d.ts","sourceRoot":"","sources":["../../../../../src/pipeline/stages/ast/rulesEnforcer.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAC;AAGpD,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,OAAO,GAAG,SAAS,GAAG,MAAM,CAAC;IACvC,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,sBAAsB;IACrC,UAAU,EAAE,aAAa,EAAE,CAAC;IAC5B,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED;;GAEG;AACH,wBAAgB,6BAA6B,CAC3C,WAAW,EAAE,oBAAoB,EACjC,WAAW,EAAE,MAAM,GAClB,sBAAsB,
|
|
1
|
+
{"version":3,"file":"rulesEnforcer.d.ts","sourceRoot":"","sources":["../../../../../src/pipeline/stages/ast/rulesEnforcer.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAC;AAGpD,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,OAAO,GAAG,SAAS,GAAG,MAAM,CAAC;IACvC,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,sBAAsB;IACrC,UAAU,EAAE,aAAa,EAAE,CAAC;IAC5B,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED;;GAEG;AACH,wBAAgB,6BAA6B,CAC3C,WAAW,EAAE,oBAAoB,EACjC,WAAW,EAAE,MAAM,GAClB,sBAAsB,CA0BxB"}
|