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.
Files changed (118) hide show
  1. package/dist/dashboard/dist/assets/_basePickBy-C2jmWITn.js +1 -0
  2. package/dist/dashboard/dist/assets/_baseUniq-DE6cyzJb.js +1 -0
  3. package/dist/dashboard/dist/assets/arc-B-Q4nGPT.js +1 -0
  4. package/dist/dashboard/dist/assets/architectureDiagram-VXUJARFQ-C_5dqWCI.js +36 -0
  5. package/dist/dashboard/dist/assets/blockDiagram-VD42YOAC-DbGIO6Kt.js +122 -0
  6. package/dist/dashboard/dist/assets/c4Diagram-YG6GDRKO-CAFpcejP.js +10 -0
  7. package/dist/dashboard/dist/assets/channel-Di9el3wE.js +1 -0
  8. package/dist/dashboard/dist/assets/chunk-4BX2VUAB-DY1boKsq.js +1 -0
  9. package/dist/dashboard/dist/assets/chunk-55IACEB6-BSL35gyW.js +1 -0
  10. package/dist/dashboard/dist/assets/chunk-B4BG7PRW-eTDXrKrv.js +165 -0
  11. package/dist/dashboard/dist/assets/chunk-DI55MBZ5-M-8I3jEy.js +220 -0
  12. package/dist/dashboard/dist/assets/chunk-FMBD7UC4-bSA0XiS0.js +15 -0
  13. package/dist/dashboard/dist/assets/chunk-QN33PNHL-BrOIYUBs.js +1 -0
  14. package/dist/dashboard/dist/assets/chunk-QZHKN3VN-CliaQGD4.js +1 -0
  15. package/dist/dashboard/dist/assets/chunk-TZMSLE5B-CyhcxGB1.js +1 -0
  16. package/dist/dashboard/dist/assets/classDiagram-2ON5EDUG-BkGN4Cpz.js +1 -0
  17. package/dist/dashboard/dist/assets/classDiagram-v2-WZHVMYZB-BkGN4Cpz.js +1 -0
  18. package/dist/dashboard/dist/assets/clone-Cvq8JuOb.js +1 -0
  19. package/dist/dashboard/dist/assets/cose-bilkent-S5V4N54A-BUkL7Wtq.js +1 -0
  20. package/dist/dashboard/dist/assets/dagre-6UL2VRFP-B8oEROJc.js +4 -0
  21. package/dist/dashboard/dist/assets/diagram-PSM6KHXK-5uki9Dw8.js +24 -0
  22. package/dist/dashboard/dist/assets/diagram-QEK2KX5R-BRNhmby2.js +43 -0
  23. package/dist/dashboard/dist/assets/diagram-S2PKOQOG-D-ku_X8U.js +24 -0
  24. package/dist/dashboard/dist/assets/erDiagram-Q2GNP2WA-DGl6gPe2.js +60 -0
  25. package/dist/dashboard/dist/assets/flowDiagram-NV44I4VS-Co89qYBD.js +162 -0
  26. package/dist/dashboard/dist/assets/ganttDiagram-JELNMOA3-2r3WpWQC.js +267 -0
  27. package/dist/dashboard/dist/assets/gitGraphDiagram-V2S2FVAM-CuJ5l3TK.js +65 -0
  28. package/dist/dashboard/dist/assets/graph-ZtgwAPQj.js +1 -0
  29. package/dist/dashboard/dist/assets/index-D3sRJga7.js +777 -0
  30. package/dist/dashboard/dist/assets/infoDiagram-HS3SLOUP-ujnMqVz3.js +2 -0
  31. package/dist/dashboard/dist/assets/journeyDiagram-XKPGCS4Q-DQzfeBIo.js +139 -0
  32. package/dist/dashboard/dist/assets/kanban-definition-3W4ZIXB7-ueIaoeks.js +89 -0
  33. package/dist/dashboard/dist/assets/layout-B1fTYUMj.js +1 -0
  34. package/dist/dashboard/dist/assets/mindmap-definition-VGOIOE7T-B7wYeLe1.js +68 -0
  35. package/dist/dashboard/dist/assets/pieDiagram-ADFJNKIX-Bf8vKEOf.js +30 -0
  36. package/dist/dashboard/dist/assets/quadrantDiagram-AYHSOK5B-CM8qiFLR.js +7 -0
  37. package/dist/dashboard/dist/assets/requirementDiagram-UZGBJVZJ-DPTtP4Ve.js +64 -0
  38. package/dist/dashboard/dist/assets/sankeyDiagram-TZEHDZUN-DEVTdH0h.js +10 -0
  39. package/dist/dashboard/dist/assets/sequenceDiagram-WL72ISMW-Bjr5wgXg.js +145 -0
  40. package/dist/dashboard/dist/assets/stateDiagram-FKZM4ZOC-DDrhZYly.js +1 -0
  41. package/dist/dashboard/dist/assets/stateDiagram-v2-4FDKWEC3-Im6pH8C-.js +1 -0
  42. package/dist/dashboard/dist/assets/timeline-definition-IT6M3QCI-DAT3r9va.js +61 -0
  43. package/dist/dashboard/dist/assets/treemap-GDKQZRPO-BlA8rg0m.js +162 -0
  44. package/dist/dashboard/dist/assets/xychartDiagram-PRI3JC2R-7aSkQtVu.js +7 -0
  45. package/dist/dashboard/dist/index.html +1 -1
  46. package/dist/src/ast/astTypes.d.ts +86 -0
  47. package/dist/src/ast/astTypes.d.ts.map +1 -1
  48. package/dist/src/discovery/frameworkDetector.d.ts +28 -0
  49. package/dist/src/discovery/frameworkDetector.d.ts.map +1 -0
  50. package/dist/src/discovery/frameworkDetector.js +189 -0
  51. package/dist/src/discovery/projectDiscovery.d.ts +5 -1
  52. package/dist/src/discovery/projectDiscovery.d.ts.map +1 -1
  53. package/dist/src/discovery/projectDiscovery.js +4 -0
  54. package/dist/src/inference/routeInference.d.ts.map +1 -1
  55. package/dist/src/inference/routeInference.js +224 -1
  56. package/dist/src/languages/java/graphqlSchemaParser.d.ts +65 -0
  57. package/dist/src/languages/java/graphqlSchemaParser.d.ts.map +1 -0
  58. package/dist/src/languages/java/graphqlSchemaParser.js +164 -0
  59. package/dist/src/languages/java/mybatisXmlParser.d.ts +52 -0
  60. package/dist/src/languages/java/mybatisXmlParser.d.ts.map +1 -0
  61. package/dist/src/languages/java/mybatisXmlParser.js +107 -0
  62. package/dist/src/languages/javascript/angularDetector.d.ts +74 -0
  63. package/dist/src/languages/javascript/angularDetector.d.ts.map +1 -0
  64. package/dist/src/languages/javascript/angularDetector.js +194 -0
  65. package/dist/src/languages/javascript/hapiDetector.d.ts +40 -0
  66. package/dist/src/languages/javascript/hapiDetector.d.ts.map +1 -0
  67. package/dist/src/languages/javascript/hapiDetector.js +131 -0
  68. package/dist/src/languages/javascript/mongooseDetector.d.ts +65 -0
  69. package/dist/src/languages/javascript/mongooseDetector.d.ts.map +1 -0
  70. package/dist/src/languages/javascript/mongooseDetector.js +237 -0
  71. package/dist/src/languages/javascript/vueDetector.d.ts +40 -0
  72. package/dist/src/languages/javascript/vueDetector.d.ts.map +1 -0
  73. package/dist/src/languages/javascript/vueDetector.js +87 -0
  74. package/dist/src/languages/python/index.d.ts +5 -1
  75. package/dist/src/languages/python/index.d.ts.map +1 -1
  76. package/dist/src/languages/python/index.js +167 -2
  77. package/dist/src/languages/python/testPatternDetector.d.ts +70 -0
  78. package/dist/src/languages/python/testPatternDetector.d.ts.map +1 -0
  79. package/dist/src/languages/python/testPatternDetector.js +201 -0
  80. package/dist/src/pipeline/stages/ast/astStage.d.ts.map +1 -1
  81. package/dist/src/pipeline/stages/ast/astStage.js +6 -0
  82. package/dist/src/pipeline/stages/ast/baseUrlComposer.d.ts +44 -0
  83. package/dist/src/pipeline/stages/ast/baseUrlComposer.d.ts.map +1 -0
  84. package/dist/src/pipeline/stages/ast/baseUrlComposer.js +83 -0
  85. package/dist/src/pipeline/stages/ast/crossFileResolutionPass.d.ts +54 -0
  86. package/dist/src/pipeline/stages/ast/crossFileResolutionPass.d.ts.map +1 -0
  87. package/dist/src/pipeline/stages/ast/crossFileResolutionPass.js +88 -0
  88. package/dist/src/pipeline/stages/ast/crossFileResolver.d.ts.map +1 -1
  89. package/dist/src/pipeline/stages/ast/crossFileResolver.js +10 -1
  90. package/dist/src/pipeline/stages/ast/optionalAuthUnifier.d.ts +39 -0
  91. package/dist/src/pipeline/stages/ast/optionalAuthUnifier.d.ts.map +1 -0
  92. package/dist/src/pipeline/stages/ast/optionalAuthUnifier.js +81 -0
  93. package/dist/src/pipeline/stages/ast/resolvers/angularInjectionResolver.d.ts +18 -0
  94. package/dist/src/pipeline/stages/ast/resolvers/angularInjectionResolver.d.ts.map +1 -0
  95. package/dist/src/pipeline/stages/ast/resolvers/angularInjectionResolver.js +77 -0
  96. package/dist/src/pipeline/stages/ast/resolvers/dddLayerResolver.d.ts +46 -0
  97. package/dist/src/pipeline/stages/ast/resolvers/dddLayerResolver.d.ts.map +1 -0
  98. package/dist/src/pipeline/stages/ast/resolvers/dddLayerResolver.js +238 -0
  99. package/dist/src/pipeline/stages/ast/resolvers/expressRouterResolver.d.ts +17 -0
  100. package/dist/src/pipeline/stages/ast/resolvers/expressRouterResolver.d.ts.map +1 -0
  101. package/dist/src/pipeline/stages/ast/resolvers/expressRouterResolver.js +65 -0
  102. package/dist/src/pipeline/stages/ast/resolvers/flaskBlueprintResolver.d.ts +17 -0
  103. package/dist/src/pipeline/stages/ast/resolvers/flaskBlueprintResolver.d.ts.map +1 -0
  104. package/dist/src/pipeline/stages/ast/resolvers/flaskBlueprintResolver.js +114 -0
  105. package/dist/src/pipeline/stages/ast/resolvers/mybatisResolver.d.ts +27 -0
  106. package/dist/src/pipeline/stages/ast/resolvers/mybatisResolver.d.ts.map +1 -0
  107. package/dist/src/pipeline/stages/ast/resolvers/mybatisResolver.js +74 -0
  108. package/dist/src/pipeline/stages/ast/resolvers/vuexActionResolver.d.ts +17 -0
  109. package/dist/src/pipeline/stages/ast/resolvers/vuexActionResolver.d.ts.map +1 -0
  110. package/dist/src/pipeline/stages/ast/resolvers/vuexActionResolver.js +55 -0
  111. package/dist/src/pipeline/stages/ast/rulesEnforcer.d.ts +24 -0
  112. package/dist/src/pipeline/stages/ast/rulesEnforcer.d.ts.map +1 -0
  113. package/dist/src/pipeline/stages/ast/rulesEnforcer.js +120 -0
  114. package/dist/src/pipeline/stages/ast/types.d.ts +114 -1
  115. package/dist/src/pipeline/stages/ast/types.d.ts.map +1 -1
  116. package/dist/src/pipeline/stages/tia/testLayerClassifier.d.ts.map +1 -1
  117. package/dist/src/pipeline/stages/tia/testLayerClassifier.js +5 -0
  118. package/package.json +1 -1
@@ -0,0 +1,81 @@
1
+ "use strict";
2
+ /**
3
+ * Optional auth unifier (Feature 27, Sub-PR 9)
4
+ *
5
+ * Normalizes all framework-specific auth classifications to a unified SecurityClassification.
6
+ * Maps framework-specific patterns:
7
+ * Flask @jwt_optional → { optional: true }
8
+ * Express auth.optional / credentialsRequired: false → { optional: true }
9
+ * HapiJS auth: { mode: 'try' } → { optional: true }
10
+ * Spring @PreAuthorize → { required: true }
11
+ * Angular route guard → depends on guard type
12
+ */
13
+ Object.defineProperty(exports, "__esModule", { value: true });
14
+ exports.unifyAuthClassification = unifyAuthClassification;
15
+ exports.detectAuthCoverageGaps = detectAuthCoverageGaps;
16
+ /**
17
+ * Framework-specific auth pattern → unified SecurityClassification.
18
+ */
19
+ function unifyAuthClassification(framework, pattern) {
20
+ const key = `${framework}:${pattern}`.toLowerCase();
21
+ // Flask patterns
22
+ if (key.includes('flask:@jwt_required') || key.includes('flask:jwt_required')) {
23
+ return { type: 'jwt', required: true, optional: false, sourcePattern: pattern };
24
+ }
25
+ if (key.includes('flask:@jwt_optional') || key.includes('flask:jwt_optional')) {
26
+ return { type: 'jwt', required: false, optional: true, sourcePattern: pattern };
27
+ }
28
+ if (key.includes('flask:@login_required') || key.includes('flask:login_required')) {
29
+ return { type: 'session', required: true, optional: false, sourcePattern: pattern };
30
+ }
31
+ // Express patterns
32
+ if (key.includes('express:auth.required') || key.includes('express:credentialsrequired: true')) {
33
+ return { type: 'jwt', required: true, optional: false, sourcePattern: pattern };
34
+ }
35
+ if (key.includes('express:auth.optional') || key.includes('express:credentialsrequired: false')) {
36
+ return { type: 'jwt', required: false, optional: true, sourcePattern: pattern };
37
+ }
38
+ if (key.includes('express:passport.authenticate')) {
39
+ return { type: 'jwt', required: true, optional: false, sourcePattern: pattern };
40
+ }
41
+ // HapiJS patterns (framework may be 'hapi' or 'hapijs')
42
+ const isHapi = key.startsWith('hapi:') || key.startsWith('hapijs:');
43
+ if (isHapi && key.includes('auth') && key.includes('mode') && (key.includes('try') || key.includes('optional'))) {
44
+ return { type: 'jwt', required: false, optional: true, sourcePattern: pattern };
45
+ }
46
+ if (isHapi && key.includes('auth') && !key.includes('false') && !key.includes('try') && !key.includes('optional')) {
47
+ return { type: 'jwt', required: true, optional: false, sourcePattern: pattern };
48
+ }
49
+ // Spring patterns
50
+ if (key.includes('spring:@preauthorize') || key.includes('spring:@secured')) {
51
+ return { type: 'custom', required: true, optional: false, sourcePattern: pattern };
52
+ }
53
+ return undefined;
54
+ }
55
+ /**
56
+ * Analyze auth coverage gaps in endpoints vs tests.
57
+ */
58
+ function detectAuthCoverageGaps(endpoints, testAssertionPaths) {
59
+ const gaps = [];
60
+ for (const ep of endpoints) {
61
+ if (!ep.security)
62
+ continue;
63
+ if (ep.security.required && !testAssertionPaths.has(ep.path)) {
64
+ gaps.push({
65
+ type: 'missing-401-test',
66
+ endpointPath: ep.path,
67
+ security: ep.security,
68
+ sourceFile: ep.sourceFile,
69
+ });
70
+ }
71
+ if (ep.security.optional && !testAssertionPaths.has(ep.path)) {
72
+ gaps.push({
73
+ type: 'missing-optional-dual-path',
74
+ endpointPath: ep.path,
75
+ security: ep.security,
76
+ sourceFile: ep.sourceFile,
77
+ });
78
+ }
79
+ }
80
+ return gaps;
81
+ }
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Angular injection cross-file resolver (Feature 27, Sub-PR 7)
3
+ *
4
+ * Resolves Angular dependency injection chains:
5
+ * 1. Constructor injection: private articlesService: ArticlesService → find ArticlesService file
6
+ * 2. inject(ArticlesService) → same resolution
7
+ * 3. Follow service methods to HttpClient calls → build chain: Component → Service → HTTP call
8
+ * 4. Resolve environment.api_url from environments/environment.ts
9
+ * 5. Link guards to routes they protect via route config canActivate arrays
10
+ */
11
+ import type { CrossFileResolver, CrossFileResolutionContext, CrossFileResolutionResult } from '../types';
12
+ import type { DetectedApiFramework } from '../../../../discovery/frameworkDetector';
13
+ export declare class AngularInjectionResolver implements CrossFileResolver {
14
+ readonly name = "angular-injection";
15
+ appliesTo(frameworks: DetectedApiFramework[]): boolean;
16
+ resolve(ctx: CrossFileResolutionContext): CrossFileResolutionResult;
17
+ }
18
+ //# sourceMappingURL=angularInjectionResolver.d.ts.map
@@ -0,0 +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;CA0CpE"}
@@ -0,0 +1,77 @@
1
+ "use strict";
2
+ /**
3
+ * Angular injection cross-file resolver (Feature 27, Sub-PR 7)
4
+ *
5
+ * Resolves Angular dependency injection chains:
6
+ * 1. Constructor injection: private articlesService: ArticlesService → find ArticlesService file
7
+ * 2. inject(ArticlesService) → same resolution
8
+ * 3. Follow service methods to HttpClient calls → build chain: Component → Service → HTTP call
9
+ * 4. Resolve environment.api_url from environments/environment.ts
10
+ * 5. Link guards to routes they protect via route config canActivate arrays
11
+ */
12
+ Object.defineProperty(exports, "__esModule", { value: true });
13
+ exports.AngularInjectionResolver = void 0;
14
+ class AngularInjectionResolver {
15
+ constructor() {
16
+ this.name = 'angular-injection';
17
+ }
18
+ appliesTo(frameworks) {
19
+ return frameworks.some((f) => f.name === 'angular');
20
+ }
21
+ resolve(ctx) {
22
+ let entriesAdded = 0;
23
+ const diagnostics = [];
24
+ const unresolvedRefs = [];
25
+ // Build injection chains from class registry
26
+ for (const [className, classInfo] of ctx.symbolTable.classes) {
27
+ // If class implements interfaces, it may be a service
28
+ if (!classInfo.implementsInterfaces)
29
+ continue;
30
+ // Look for classes that have methods making HTTP calls
31
+ const model = ctx.symbolTable.models.get(classInfo.filePath);
32
+ if (!model)
33
+ continue;
34
+ // Check if any function makes HTTP calls
35
+ for (const [, func] of model.functions) {
36
+ if (func.bodyHttpCalls.length > 0) {
37
+ // This is an API service — create injection chains for any class that injects it
38
+ const consumers = findConsumers(className, ctx);
39
+ for (const consumer of consumers) {
40
+ if (!ctx.symbolTable.injectionChains.has(consumer.file)) {
41
+ ctx.symbolTable.injectionChains.set(consumer.file, []);
42
+ }
43
+ ctx.symbolTable.injectionChains.get(consumer.file).push({
44
+ consumerFile: consumer.file,
45
+ consumerClass: consumer.className,
46
+ serviceClass: className,
47
+ serviceFile: classInfo.filePath,
48
+ injectionStyle: consumer.style,
49
+ });
50
+ entriesAdded++;
51
+ }
52
+ }
53
+ }
54
+ }
55
+ if (entriesAdded > 0) {
56
+ diagnostics.push(`Resolved ${entriesAdded} Angular injection chain(s)`);
57
+ }
58
+ return { entriesAdded, diagnostics, unresolvedRefs };
59
+ }
60
+ }
61
+ exports.AngularInjectionResolver = AngularInjectionResolver;
62
+ function findConsumers(serviceName, ctx) {
63
+ const consumers = [];
64
+ // Check existing injection chains (may have been populated by angularDetector)
65
+ for (const [file, chains] of ctx.symbolTable.injectionChains) {
66
+ for (const chain of chains) {
67
+ if (chain.serviceClass === serviceName) {
68
+ consumers.push({
69
+ className: chain.consumerClass,
70
+ file: chain.consumerFile,
71
+ style: chain.injectionStyle,
72
+ });
73
+ }
74
+ }
75
+ }
76
+ return consumers;
77
+ }
@@ -0,0 +1,46 @@
1
+ /**
2
+ * DDD / CQRS / Hexagonal layer resolver (Feature 27, Sub-PR 5)
3
+ *
4
+ * Resolves DDD-structured Java projects without requiring @Service/@Repository annotations.
5
+ * Detects:
6
+ * 1. Repository interfaces (findBy*, save, delete methods)
7
+ * 2. Interface → implementation mapping (implements InterfaceName)
8
+ * 3. CQRS command/query handlers (execute/handle/apply taking *Command/*Query)
9
+ * 4. Package-name layer hints (domain, application, infrastructure, adapter) as tie-breakers only
10
+ */
11
+ import type { CrossFileResolver, CrossFileResolutionContext, CrossFileResolutionResult } from '../types';
12
+ import type { DetectedApiFramework } from '../../../../discovery/frameworkDetector';
13
+ export interface DddRepositoryInterface {
14
+ interfaceName: string;
15
+ methods: string[];
16
+ sourceFile: string;
17
+ line?: number;
18
+ }
19
+ export interface DddCqrsHandler {
20
+ className: string;
21
+ handlerType: 'command' | 'query' | 'event';
22
+ handleMethodName: string;
23
+ parameterType: string;
24
+ sourceFile: string;
25
+ line?: number;
26
+ }
27
+ export declare class DddLayerResolver implements CrossFileResolver {
28
+ readonly name = "ddd-layer";
29
+ appliesTo(frameworks: DetectedApiFramework[]): boolean;
30
+ resolve(ctx: CrossFileResolutionContext): CrossFileResolutionResult;
31
+ }
32
+ /**
33
+ * Detect repository interfaces: interfaces with findBy*, save, delete, etc.
34
+ * No @Repository annotation required (RULE-SA03).
35
+ */
36
+ export declare function detectRepositoryInterfaces(source: string, filePath: string): DddRepositoryInterface[];
37
+ /**
38
+ * Detect CQRS command/query handlers.
39
+ * Looks for classes with execute/handle/apply methods that take *Command/*Query parameters.
40
+ */
41
+ export declare function detectCqrsHandlers(source: string, filePath: string): DddCqrsHandler[];
42
+ /**
43
+ * Detect implements clauses from Java/Kotlin source.
44
+ */
45
+ export declare function detectImplementsClauses(source: string, filePath: string): Array<[string, string]>;
46
+ //# sourceMappingURL=dddLayerResolver.d.ts.map
@@ -0,0 +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;CAqEpE;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"}
@@ -0,0 +1,238 @@
1
+ "use strict";
2
+ /**
3
+ * DDD / CQRS / Hexagonal layer resolver (Feature 27, Sub-PR 5)
4
+ *
5
+ * Resolves DDD-structured Java projects without requiring @Service/@Repository annotations.
6
+ * Detects:
7
+ * 1. Repository interfaces (findBy*, save, delete methods)
8
+ * 2. Interface → implementation mapping (implements InterfaceName)
9
+ * 3. CQRS command/query handlers (execute/handle/apply taking *Command/*Query)
10
+ * 4. Package-name layer hints (domain, application, infrastructure, adapter) as tie-breakers only
11
+ */
12
+ Object.defineProperty(exports, "__esModule", { value: true });
13
+ exports.DddLayerResolver = void 0;
14
+ exports.detectRepositoryInterfaces = detectRepositoryInterfaces;
15
+ exports.detectCqrsHandlers = detectCqrsHandlers;
16
+ exports.detectImplementsClauses = detectImplementsClauses;
17
+ class DddLayerResolver {
18
+ constructor() {
19
+ this.name = 'ddd-layer';
20
+ }
21
+ appliesTo(frameworks) {
22
+ return frameworks.some((f) => f.name === 'spring-boot' || f.name === 'spring-graphql' || f.name === 'dgs-framework');
23
+ }
24
+ resolve(ctx) {
25
+ let entriesAdded = 0;
26
+ const diagnostics = [];
27
+ const unresolvedRefs = [];
28
+ const repoInterfaces = [];
29
+ const cqrsHandlers = [];
30
+ const implementations = new Map();
31
+ for (const [filePath, model] of ctx.symbolTable.models) {
32
+ const sourceText = getSourceText(filePath, ctx);
33
+ if (!sourceText)
34
+ continue;
35
+ // Detect repository interfaces
36
+ const repos = detectRepositoryInterfaces(sourceText, filePath);
37
+ repoInterfaces.push(...repos);
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, []);
46
+ }
47
+ implementations.get(ifaceName).push(implName);
48
+ }
49
+ }
50
+ // Map interface → implementation in symbolTable
51
+ for (const [ifaceName, implNames] of implementations) {
52
+ for (const implName of implNames) {
53
+ const ifaceFile = findFileForClass(ifaceName, ctx);
54
+ const implFile = findFileForClass(implName, ctx);
55
+ if (ifaceFile && implFile) {
56
+ if (!ctx.symbolTable.interfaceImplementations.has(ifaceFile)) {
57
+ ctx.symbolTable.interfaceImplementations.set(ifaceFile, []);
58
+ }
59
+ ctx.symbolTable.interfaceImplementations.get(ifaceFile).push({
60
+ interfaceName: ifaceName,
61
+ interfaceFile: ifaceFile,
62
+ implName,
63
+ implFile,
64
+ });
65
+ entriesAdded++;
66
+ }
67
+ else if (!implFile) {
68
+ unresolvedRefs.push({
69
+ ref: implName,
70
+ reason: `Implementation class '${implName}' not found in parsed models`,
71
+ });
72
+ }
73
+ }
74
+ }
75
+ if (repoInterfaces.length > 0) {
76
+ diagnostics.push(`Found ${repoInterfaces.length} repository interface(s)`);
77
+ }
78
+ if (cqrsHandlers.length > 0) {
79
+ diagnostics.push(`Found ${cqrsHandlers.length} CQRS handler(s)`);
80
+ }
81
+ if (implementations.size > 0) {
82
+ diagnostics.push(`Found ${implementations.size} interface→implementation mapping(s)`);
83
+ }
84
+ return { entriesAdded, diagnostics, unresolvedRefs };
85
+ }
86
+ }
87
+ exports.DddLayerResolver = DddLayerResolver;
88
+ /**
89
+ * Detect repository interfaces: interfaces with findBy*, save, delete, etc.
90
+ * No @Repository annotation required (RULE-SA03).
91
+ */
92
+ function detectRepositoryInterfaces(source, filePath) {
93
+ const repos = [];
94
+ const lines = source.split('\n');
95
+ // Find interfaces
96
+ const interfacePattern = /(?:public\s+)?interface\s+(\w+(?:Repository|Repo|Store|Gateway))\b/;
97
+ let currentInterface = null;
98
+ let braceDepth = 0;
99
+ for (let i = 0; i < lines.length; i++) {
100
+ const line = lines[i];
101
+ if (!currentInterface) {
102
+ const match = line.match(interfacePattern);
103
+ if (match) {
104
+ currentInterface = {
105
+ interfaceName: match[1],
106
+ methods: [],
107
+ sourceFile: filePath,
108
+ line: i + 1,
109
+ };
110
+ braceDepth = 0;
111
+ }
112
+ }
113
+ if (currentInterface) {
114
+ braceDepth += (line.match(/\{/g) || []).length;
115
+ braceDepth -= (line.match(/\}/g) || []).length;
116
+ // Detect repository methods: findByX, save, delete, existsBy, countBy
117
+ const methodMatch = line.match(/\b(findBy\w+|find\w+|save|saveAll|delete|deleteById|existsBy\w+|countBy\w+|getBy\w+)\s*\(/);
118
+ if (methodMatch) {
119
+ currentInterface.methods.push(methodMatch[1]);
120
+ }
121
+ if (braceDepth <= 0 && currentInterface.methods.length > 0) {
122
+ repos.push(currentInterface);
123
+ currentInterface = null;
124
+ }
125
+ else if (braceDepth <= 0) {
126
+ currentInterface = null;
127
+ }
128
+ }
129
+ }
130
+ // Also detect interfaces with standard CRUD method signatures without naming convention
131
+ const genericInterfacePattern = /(?:public\s+)?interface\s+(\w+)\b/g;
132
+ let genMatch;
133
+ while ((genMatch = genericInterfacePattern.exec(source)) !== null) {
134
+ const name = genMatch[1];
135
+ // Skip if already detected
136
+ if (repos.some((r) => r.interfaceName === name))
137
+ continue;
138
+ // Check if this interface has findBy, save, delete methods
139
+ const startIdx = genMatch.index;
140
+ const braceIdx = source.indexOf('{', startIdx);
141
+ if (braceIdx < 0)
142
+ continue;
143
+ let depth = 1;
144
+ let endIdx = braceIdx + 1;
145
+ while (endIdx < source.length && depth > 0) {
146
+ if (source[endIdx] === '{')
147
+ depth++;
148
+ if (source[endIdx] === '}')
149
+ depth--;
150
+ endIdx++;
151
+ }
152
+ const body = source.substring(braceIdx, endIdx);
153
+ const methods = [];
154
+ const repoMethodPattern = /\b(findBy\w+|save|delete|deleteById)\s*\(/g;
155
+ let rm;
156
+ while ((rm = repoMethodPattern.exec(body)) !== null) {
157
+ methods.push(rm[1]);
158
+ }
159
+ if (methods.length >= 2) {
160
+ const lineNum = source.substring(0, startIdx).split('\n').length;
161
+ repos.push({ interfaceName: name, methods, sourceFile: filePath, line: lineNum });
162
+ }
163
+ }
164
+ return repos;
165
+ }
166
+ /**
167
+ * Detect CQRS command/query handlers.
168
+ * Looks for classes with execute/handle/apply methods that take *Command/*Query parameters.
169
+ */
170
+ function detectCqrsHandlers(source, filePath) {
171
+ const handlers = [];
172
+ const lines = source.split('\n');
173
+ // Pattern: handle(CreateArticleCommand cmd) or execute(GetArticlesQuery query)
174
+ const handlerMethodPattern = /(?:public\s+\S+\s+)?(execute|handle|apply)\s*\(\s*(\w+(Command|Query|Event))\s+\w+\s*\)/;
175
+ // Find the enclosing class name
176
+ let currentClass = '';
177
+ for (let i = 0; i < lines.length; i++) {
178
+ const line = lines[i];
179
+ const classMatch = line.match(/class\s+(\w+)/);
180
+ if (classMatch) {
181
+ currentClass = classMatch[1];
182
+ }
183
+ const methodMatch = line.match(handlerMethodPattern);
184
+ if (methodMatch && currentClass) {
185
+ const handlerType = methodMatch[3].toLowerCase();
186
+ handlers.push({
187
+ className: currentClass,
188
+ handlerType,
189
+ handleMethodName: methodMatch[1],
190
+ parameterType: methodMatch[2],
191
+ sourceFile: filePath,
192
+ line: i + 1,
193
+ });
194
+ }
195
+ }
196
+ return handlers;
197
+ }
198
+ /**
199
+ * Detect implements clauses from Java/Kotlin source.
200
+ */
201
+ function detectImplementsClauses(source, filePath) {
202
+ const impls = [];
203
+ const pattern = /class\s+(\w+)(?:\s+extends\s+\w+)?\s+implements\s+([\w,\s]+)/g;
204
+ let match;
205
+ while ((match = pattern.exec(source)) !== null) {
206
+ const className = match[1];
207
+ const interfaces = match[2].split(',').map((s) => s.trim()).filter((s) => s.length > 0);
208
+ for (const iface of interfaces) {
209
+ impls.push([iface, className]);
210
+ }
211
+ }
212
+ return impls;
213
+ }
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
+ function findFileForClass(className, ctx) {
228
+ // Search through exported symbols and class registry
229
+ const classInfo = ctx.symbolTable.classes.get(className);
230
+ if (classInfo)
231
+ return classInfo.filePath;
232
+ // Search through models for any mention
233
+ for (const [filePath, model] of ctx.symbolTable.models) {
234
+ if (model.functions.has(className))
235
+ return filePath;
236
+ }
237
+ return undefined;
238
+ }
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Express router cross-file resolver (Feature 27, Sub-PR 6)
3
+ *
4
+ * Resolves Express `app.use('/prefix', router)` mount paths across files:
5
+ * 1. Find all app.use('/path', require('./routes')) calls → mount registry
6
+ * 2. Follow require('./routes') to resolve sub-router files
7
+ * 3. Propagate auth middleware through nested routers
8
+ * 4. Build complete URL: base mount + sub-router mount + route path
9
+ */
10
+ import type { CrossFileResolver, CrossFileResolutionContext, CrossFileResolutionResult } from '../types';
11
+ import type { DetectedApiFramework } from '../../../../discovery/frameworkDetector';
12
+ export declare class ExpressRouterResolver implements CrossFileResolver {
13
+ readonly name = "express-router";
14
+ appliesTo(frameworks: DetectedApiFramework[]): boolean;
15
+ resolve(ctx: CrossFileResolutionContext): CrossFileResolutionResult;
16
+ }
17
+ //# sourceMappingURL=expressRouterResolver.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"expressRouterResolver.d.ts","sourceRoot":"","sources":["../../../../../../src/pipeline/stages/ast/resolvers/expressRouterResolver.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,qBAAsB,YAAW,iBAAiB;IAC7D,QAAQ,CAAC,IAAI,oBAAoB;IAEjC,SAAS,CAAC,UAAU,EAAE,oBAAoB,EAAE,GAAG,OAAO;IAMtD,OAAO,CAAC,GAAG,EAAE,0BAA0B,GAAG,yBAAyB;CAiDpE"}
@@ -0,0 +1,65 @@
1
+ "use strict";
2
+ /**
3
+ * Express router cross-file resolver (Feature 27, Sub-PR 6)
4
+ *
5
+ * Resolves Express `app.use('/prefix', router)` mount paths across files:
6
+ * 1. Find all app.use('/path', require('./routes')) calls → mount registry
7
+ * 2. Follow require('./routes') to resolve sub-router files
8
+ * 3. Propagate auth middleware through nested routers
9
+ * 4. Build complete URL: base mount + sub-router mount + route path
10
+ */
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.ExpressRouterResolver = void 0;
13
+ class ExpressRouterResolver {
14
+ constructor() {
15
+ this.name = 'express-router';
16
+ }
17
+ appliesTo(frameworks) {
18
+ return frameworks.some((f) => f.name === 'express' || f.name === 'nestjs' || f.name === 'koa' || f.name === 'fastify');
19
+ }
20
+ resolve(ctx) {
21
+ let entriesAdded = 0;
22
+ const diagnostics = [];
23
+ const unresolvedRefs = [];
24
+ // Scan models for Express router mount patterns
25
+ for (const [filePath, model] of ctx.symbolTable.models) {
26
+ if (!model.routeRegistrations)
27
+ continue;
28
+ for (const reg of model.routeRegistrations) {
29
+ // app.use('/prefix', require('./router'))
30
+ if (reg.targetModule && reg.path) {
31
+ if (!ctx.symbolTable.routerMounts.has(filePath)) {
32
+ ctx.symbolTable.routerMounts.set(filePath, []);
33
+ }
34
+ ctx.symbolTable.routerMounts.get(filePath).push({
35
+ prefix: reg.path,
36
+ targetModulePath: reg.targetModule,
37
+ middleware: [],
38
+ sourceFile: filePath,
39
+ line: reg.line,
40
+ });
41
+ entriesAdded++;
42
+ }
43
+ }
44
+ }
45
+ // Propagate middleware from router mounts to sub-routes
46
+ for (const [filePath, mounts] of ctx.symbolTable.routerMounts) {
47
+ for (const mount of mounts) {
48
+ // Check if auth middleware is applied to this mount
49
+ const middleware = ctx.symbolTable.middlewareInheritance.get(filePath);
50
+ if (middleware) {
51
+ for (const mw of middleware) {
52
+ if (mw.appliedTo === 'router') {
53
+ mount.middleware.push(mw);
54
+ }
55
+ }
56
+ }
57
+ }
58
+ }
59
+ if (entriesAdded > 0) {
60
+ diagnostics.push(`Resolved ${entriesAdded} Express router mount(s)`);
61
+ }
62
+ return { entriesAdded, diagnostics, unresolvedRefs };
63
+ }
64
+ }
65
+ exports.ExpressRouterResolver = ExpressRouterResolver;
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Flask Blueprint cross-file resolver (Feature 27)
3
+ *
4
+ * Resolves Flask Blueprint route URLs across files by:
5
+ * 1. Finding all Blueprint() constructor calls → blueprint registry
6
+ * 2. Finding all app.register_blueprint() calls with url_prefix
7
+ * 3. Matching blueprint vars across files via import resolution
8
+ * 4. Composing final URL: url_prefix + route_path
9
+ */
10
+ import type { CrossFileResolver, CrossFileResolutionContext, CrossFileResolutionResult } from '../types';
11
+ import type { DetectedApiFramework } from '../../../../discovery/frameworkDetector';
12
+ export declare class FlaskBlueprintResolver implements CrossFileResolver {
13
+ readonly name = "flask-blueprint";
14
+ appliesTo(frameworks: DetectedApiFramework[]): boolean;
15
+ resolve(ctx: CrossFileResolutionContext): CrossFileResolutionResult;
16
+ }
17
+ //# sourceMappingURL=flaskBlueprintResolver.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"flaskBlueprintResolver.d.ts","sourceRoot":"","sources":["../../../../../../src/pipeline/stages/ast/resolvers/flaskBlueprintResolver.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EACV,iBAAiB,EACjB,0BAA0B,EAC1B,yBAAyB,EAE1B,MAAM,UAAU,CAAC;AAClB,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,yCAAyC,CAAC;AAGpF,qBAAa,sBAAuB,YAAW,iBAAiB;IAC9D,QAAQ,CAAC,IAAI,qBAAqB;IAElC,SAAS,CAAC,UAAU,EAAE,oBAAoB,EAAE,GAAG,OAAO;IAItD,OAAO,CAAC,GAAG,EAAE,0BAA0B,GAAG,yBAAyB;CAsGpE"}