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
|
@@ -0,0 +1,269 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Feature 28 — Test Generation & Quality Intelligence Engine
|
|
3
|
+
* Type definitions for the test generation pipeline.
|
|
4
|
+
*/
|
|
5
|
+
export type GapType = 'endpoint' | 'parameter' | 'error' | 'business' | 'integration' | 'security' | 'auth';
|
|
6
|
+
export type GapPriority = 'P0' | 'P1' | 'P2' | 'P3' | 'P4' | 'P5';
|
|
7
|
+
export type TestType = 'unit' | 'integration' | 'cypress' | 'security';
|
|
8
|
+
export type HttpMethod = 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH' | 'HEAD' | 'OPTIONS';
|
|
9
|
+
export type AuthType = 'jwt' | 'basic' | 'oauth2' | 'apikey';
|
|
10
|
+
export type ParameterLocation = 'query' | 'path' | 'header' | 'body';
|
|
11
|
+
export type MissingCase = 'boundary-min' | 'boundary-max' | 'invalid-type' | 'missing-required' | 'sql-injection' | 'xss';
|
|
12
|
+
export type SecurityControlType = 'sql-injection' | 'xss' | 'auth-bypass' | 'rate-limit' | 'mass-assignment';
|
|
13
|
+
export type FileNamingConvention = 'kebab' | 'camelCase' | 'snake_case';
|
|
14
|
+
export interface DetectedGap {
|
|
15
|
+
id: string;
|
|
16
|
+
type: GapType;
|
|
17
|
+
priority: GapPriority;
|
|
18
|
+
riskScore: number;
|
|
19
|
+
endpoint: {
|
|
20
|
+
method: HttpMethod;
|
|
21
|
+
path: string;
|
|
22
|
+
operationId?: string;
|
|
23
|
+
summary?: string;
|
|
24
|
+
tags?: string[];
|
|
25
|
+
auth: {
|
|
26
|
+
required: boolean;
|
|
27
|
+
optional: boolean;
|
|
28
|
+
type?: AuthType;
|
|
29
|
+
headerName?: string;
|
|
30
|
+
scheme?: string;
|
|
31
|
+
};
|
|
32
|
+
};
|
|
33
|
+
parameters?: ParameterInfo[];
|
|
34
|
+
responses?: ResponseInfo[];
|
|
35
|
+
businessRule?: BusinessRuleInfo;
|
|
36
|
+
securityControl?: SecurityControlInfo;
|
|
37
|
+
flow?: FlowInfo;
|
|
38
|
+
}
|
|
39
|
+
export interface ParameterInfo {
|
|
40
|
+
name: string;
|
|
41
|
+
in: ParameterLocation;
|
|
42
|
+
required: boolean;
|
|
43
|
+
schema: {
|
|
44
|
+
type: string;
|
|
45
|
+
format?: string;
|
|
46
|
+
minimum?: number;
|
|
47
|
+
maximum?: number;
|
|
48
|
+
minLength?: number;
|
|
49
|
+
maxLength?: number;
|
|
50
|
+
enum?: unknown[];
|
|
51
|
+
pattern?: string;
|
|
52
|
+
};
|
|
53
|
+
missingCases: MissingCase[];
|
|
54
|
+
}
|
|
55
|
+
export interface ResponseInfo {
|
|
56
|
+
statusCode: number;
|
|
57
|
+
description?: string;
|
|
58
|
+
schema?: unknown;
|
|
59
|
+
}
|
|
60
|
+
export interface BusinessRuleInfo {
|
|
61
|
+
id: string;
|
|
62
|
+
description: string;
|
|
63
|
+
condition: string;
|
|
64
|
+
acceptanceCriteria: string[];
|
|
65
|
+
}
|
|
66
|
+
export interface SecurityControlInfo {
|
|
67
|
+
type: SecurityControlType;
|
|
68
|
+
description: string;
|
|
69
|
+
attackVector: string;
|
|
70
|
+
expectedStatusCode: number;
|
|
71
|
+
}
|
|
72
|
+
export interface FlowInfo {
|
|
73
|
+
id: string;
|
|
74
|
+
name: string;
|
|
75
|
+
steps: Array<{
|
|
76
|
+
method: string;
|
|
77
|
+
path: string;
|
|
78
|
+
description: string;
|
|
79
|
+
}>;
|
|
80
|
+
missingStepIndex: number;
|
|
81
|
+
}
|
|
82
|
+
export interface GenerationContext {
|
|
83
|
+
gap: {
|
|
84
|
+
id: string;
|
|
85
|
+
type: GapType;
|
|
86
|
+
priority: GapPriority;
|
|
87
|
+
riskScore: number;
|
|
88
|
+
};
|
|
89
|
+
endpoint: {
|
|
90
|
+
method: string;
|
|
91
|
+
path: string;
|
|
92
|
+
pathNormalized: string;
|
|
93
|
+
operationId?: string;
|
|
94
|
+
summary?: string;
|
|
95
|
+
tags?: string[];
|
|
96
|
+
auth: {
|
|
97
|
+
required: boolean;
|
|
98
|
+
optional: boolean;
|
|
99
|
+
type?: AuthType;
|
|
100
|
+
headerName?: string;
|
|
101
|
+
scheme?: string;
|
|
102
|
+
};
|
|
103
|
+
};
|
|
104
|
+
parameters: ParameterInfo[];
|
|
105
|
+
responses: ResponseInfo[];
|
|
106
|
+
fixtures: {
|
|
107
|
+
validPayload: Record<string, unknown>;
|
|
108
|
+
invalidPayload: Record<string, unknown>;
|
|
109
|
+
authToken: string;
|
|
110
|
+
pathParams: Record<string, string>;
|
|
111
|
+
};
|
|
112
|
+
project: {
|
|
113
|
+
name: string;
|
|
114
|
+
language: string;
|
|
115
|
+
framework: string;
|
|
116
|
+
testFramework: string;
|
|
117
|
+
baseUrl: string;
|
|
118
|
+
importPrefix: string;
|
|
119
|
+
};
|
|
120
|
+
businessRule?: BusinessRuleInfo;
|
|
121
|
+
securityControl?: SecurityControlInfo;
|
|
122
|
+
flow?: FlowInfo;
|
|
123
|
+
}
|
|
124
|
+
export interface GeneratedFile {
|
|
125
|
+
gapId: string;
|
|
126
|
+
filePath: string;
|
|
127
|
+
relativePath: string;
|
|
128
|
+
content: string;
|
|
129
|
+
testType: TestType;
|
|
130
|
+
language: string;
|
|
131
|
+
framework: string;
|
|
132
|
+
}
|
|
133
|
+
export interface GenerationResult {
|
|
134
|
+
files: GeneratedFile[];
|
|
135
|
+
dryRun: boolean;
|
|
136
|
+
totalGaps: number;
|
|
137
|
+
generatedCount: number;
|
|
138
|
+
skippedCount: number;
|
|
139
|
+
errors: Array<{
|
|
140
|
+
gapId: string;
|
|
141
|
+
message: string;
|
|
142
|
+
}>;
|
|
143
|
+
}
|
|
144
|
+
export interface GenerationOptions {
|
|
145
|
+
reportsDir: string;
|
|
146
|
+
outDir: string;
|
|
147
|
+
language?: string;
|
|
148
|
+
framework?: string;
|
|
149
|
+
priority?: GapPriority;
|
|
150
|
+
dryRun?: boolean;
|
|
151
|
+
overwrite?: boolean;
|
|
152
|
+
gapId?: string;
|
|
153
|
+
types?: GapType[];
|
|
154
|
+
noSecurity?: boolean;
|
|
155
|
+
noCypress?: boolean;
|
|
156
|
+
}
|
|
157
|
+
export interface QualityDimensions {
|
|
158
|
+
assertionDepth: number;
|
|
159
|
+
negativePathCoverage: number;
|
|
160
|
+
authCoverage: number;
|
|
161
|
+
boundaryCoverage: number;
|
|
162
|
+
testIndependence: number;
|
|
163
|
+
}
|
|
164
|
+
export interface FileQualityScore {
|
|
165
|
+
file: string;
|
|
166
|
+
score: number;
|
|
167
|
+
dimensions: QualityDimensions;
|
|
168
|
+
issues: string[];
|
|
169
|
+
strengths: string[];
|
|
170
|
+
}
|
|
171
|
+
export interface HighRiskLowQualityGap {
|
|
172
|
+
endpoint: string;
|
|
173
|
+
qualityScore: number;
|
|
174
|
+
riskScore: number;
|
|
175
|
+
primaryIssue: string;
|
|
176
|
+
}
|
|
177
|
+
export interface TestQualityReport {
|
|
178
|
+
overallScore: number;
|
|
179
|
+
byFile: FileQualityScore[];
|
|
180
|
+
lowestQualityFiles: string[];
|
|
181
|
+
highestRiskLowQualityGaps: HighRiskLowQualityGap[];
|
|
182
|
+
}
|
|
183
|
+
export interface QualityScorerOptions {
|
|
184
|
+
testsGlob?: string;
|
|
185
|
+
reportsDir?: string;
|
|
186
|
+
failBelow?: number;
|
|
187
|
+
}
|
|
188
|
+
export interface MissingTestCase {
|
|
189
|
+
id: string;
|
|
190
|
+
description: string;
|
|
191
|
+
expectedStatus: number;
|
|
192
|
+
}
|
|
193
|
+
export interface AiFlowGap {
|
|
194
|
+
gapId: string;
|
|
195
|
+
priority: GapPriority;
|
|
196
|
+
riskScore: number;
|
|
197
|
+
type: GapType;
|
|
198
|
+
endpoint: {
|
|
199
|
+
method: string;
|
|
200
|
+
path: string;
|
|
201
|
+
auth: {
|
|
202
|
+
required: boolean;
|
|
203
|
+
type?: AuthType;
|
|
204
|
+
scheme?: string;
|
|
205
|
+
};
|
|
206
|
+
};
|
|
207
|
+
missingTestCases: MissingTestCase[];
|
|
208
|
+
requestSchema?: unknown;
|
|
209
|
+
responseSchema?: unknown;
|
|
210
|
+
copilotPrompt: string;
|
|
211
|
+
suggestedOutputPath: string;
|
|
212
|
+
existingSimilarTests: string[];
|
|
213
|
+
generatedCode?: string;
|
|
214
|
+
}
|
|
215
|
+
export interface AiReadyFlows {
|
|
216
|
+
generatedAt: string;
|
|
217
|
+
project: {
|
|
218
|
+
name: string;
|
|
219
|
+
language: string;
|
|
220
|
+
testFramework: string;
|
|
221
|
+
appImportPath: string;
|
|
222
|
+
};
|
|
223
|
+
gaps: AiFlowGap[];
|
|
224
|
+
}
|
|
225
|
+
export interface AiFlowExporterOptions {
|
|
226
|
+
reportsDir: string;
|
|
227
|
+
outDir: string;
|
|
228
|
+
format?: 'markdown' | 'json' | 'both';
|
|
229
|
+
maxGaps?: number;
|
|
230
|
+
priority?: GapPriority;
|
|
231
|
+
}
|
|
232
|
+
export interface GenerationConfig {
|
|
233
|
+
enabled?: boolean;
|
|
234
|
+
outputDir?: string;
|
|
235
|
+
dryRun?: boolean;
|
|
236
|
+
overwrite?: boolean;
|
|
237
|
+
minPriority?: GapPriority;
|
|
238
|
+
unitFramework?: string;
|
|
239
|
+
integrationFramework?: string;
|
|
240
|
+
e2eFramework?: string;
|
|
241
|
+
fileNaming?: FileNamingConvention;
|
|
242
|
+
includeTypes?: GapType[];
|
|
243
|
+
securityTests?: {
|
|
244
|
+
enabled?: boolean;
|
|
245
|
+
includeInjection?: boolean;
|
|
246
|
+
includeAuthBypass?: boolean;
|
|
247
|
+
includeRateLimit?: boolean;
|
|
248
|
+
};
|
|
249
|
+
fixtures?: {
|
|
250
|
+
authTokenPlaceholder?: string;
|
|
251
|
+
baseUrl?: string;
|
|
252
|
+
};
|
|
253
|
+
}
|
|
254
|
+
export interface TestQualityConfig {
|
|
255
|
+
enabled?: boolean;
|
|
256
|
+
minimumScore?: number;
|
|
257
|
+
enforceOnGlob?: string;
|
|
258
|
+
excludeGlob?: string;
|
|
259
|
+
outputPath?: string;
|
|
260
|
+
}
|
|
261
|
+
export interface AiFlowsConfig {
|
|
262
|
+
enabled?: boolean;
|
|
263
|
+
outputDir?: string;
|
|
264
|
+
maxGapsPerExport?: number;
|
|
265
|
+
minPriority?: GapPriority;
|
|
266
|
+
includeGeneratedCode?: boolean;
|
|
267
|
+
copilotPromptMaxTokens?: number;
|
|
268
|
+
}
|
|
269
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/generation/types.ts"],"names":[],"mappings":"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"}
|
package/dist/src/index.js
CHANGED
|
@@ -63,6 +63,7 @@ const integrationFlowInference_1 = require("./inference/integrationFlowInference
|
|
|
63
63
|
const routeInference_1 = require("./inference/routeInference");
|
|
64
64
|
const scanManifest_1 = require("./inference/scanManifest");
|
|
65
65
|
const serveDashboard_1 = require("./serveDashboard");
|
|
66
|
+
const index_4 = require("./generation/index");
|
|
66
67
|
// Register all language AST analyzers at startup.
|
|
67
68
|
// This side-effect import ensures each language module's registerAnalyzer() call runs.
|
|
68
69
|
(0, astAnalysisOrchestrator_1.registerAllAnalyzers)();
|
|
@@ -2044,6 +2045,118 @@ program
|
|
|
2044
2045
|
});
|
|
2045
2046
|
// Keep the process alive while the server runs
|
|
2046
2047
|
});
|
|
2048
|
+
program
|
|
2049
|
+
.command('generate-tests')
|
|
2050
|
+
.description('Generate test scaffolds for detected coverage gaps')
|
|
2051
|
+
.option('--reports-dir <dir>', 'Directory with coverage reports', 'reports/')
|
|
2052
|
+
.option('--out-dir <dir>', 'Output directory for generated tests', 'generated-tests/')
|
|
2053
|
+
.option('--language <lang>', 'Target language override (auto-detected if omitted)')
|
|
2054
|
+
.option('--framework <fw>', 'Test framework override (auto-detected if omitted)')
|
|
2055
|
+
.option('--priority <p>', 'Only generate for gaps at this priority or higher', 'P1')
|
|
2056
|
+
.option('--dry-run', 'Print generated tests to stdout, do not write files', false)
|
|
2057
|
+
.option('--overwrite', 'Overwrite existing generated files', false)
|
|
2058
|
+
.option('--gap-id <id>', 'Generate tests for a single specific gap')
|
|
2059
|
+
.option('--types <list>', 'Comma-separated gap types to generate (default: all)')
|
|
2060
|
+
.option('--no-security', 'Skip security test generation')
|
|
2061
|
+
.option('--no-cypress', 'Skip Cypress test generation')
|
|
2062
|
+
.action(async (options) => {
|
|
2063
|
+
const types = options.types
|
|
2064
|
+
? options.types.split(',').map(t => t.trim())
|
|
2065
|
+
: undefined;
|
|
2066
|
+
const result = await (0, index_4.generateTests)({
|
|
2067
|
+
reportsDir: options.reportsDir,
|
|
2068
|
+
outDir: options.outDir,
|
|
2069
|
+
language: options.language,
|
|
2070
|
+
framework: options.framework,
|
|
2071
|
+
priority: options.priority,
|
|
2072
|
+
dryRun: Boolean(options.dryRun),
|
|
2073
|
+
overwrite: Boolean(options.overwrite),
|
|
2074
|
+
gapId: options.gapId,
|
|
2075
|
+
types,
|
|
2076
|
+
noSecurity: Boolean(options.noSecurity),
|
|
2077
|
+
noCypress: Boolean(options.noCypress),
|
|
2078
|
+
});
|
|
2079
|
+
if (result.dryRun) {
|
|
2080
|
+
for (const file of result.files) {
|
|
2081
|
+
console.log(`\n${'='.repeat(60)}`);
|
|
2082
|
+
console.log(`// FILE: ${file.relativePath}`);
|
|
2083
|
+
console.log(`${'='.repeat(60)}`);
|
|
2084
|
+
console.log(file.content);
|
|
2085
|
+
}
|
|
2086
|
+
}
|
|
2087
|
+
else {
|
|
2088
|
+
console.log(`\nTest generation complete:`);
|
|
2089
|
+
console.log(` Gaps processed: ${result.totalGaps}`);
|
|
2090
|
+
console.log(` Files generated: ${result.generatedCount}`);
|
|
2091
|
+
console.log(` Errors: ${result.errors.length}`);
|
|
2092
|
+
if (result.errors.length > 0) {
|
|
2093
|
+
for (const err of result.errors) {
|
|
2094
|
+
console.error(` ERROR [${err.gapId}]: ${err.message}`);
|
|
2095
|
+
}
|
|
2096
|
+
}
|
|
2097
|
+
}
|
|
2098
|
+
});
|
|
2099
|
+
program
|
|
2100
|
+
.command('export-ai-flows')
|
|
2101
|
+
.description('Export AI-ready flow documentation for Copilot/Cursor/Claude')
|
|
2102
|
+
.option('--reports-dir <dir>', 'Directory with coverage reports', 'reports/')
|
|
2103
|
+
.option('--out-dir <dir>', 'Output directory for AI flow files', 'reports/')
|
|
2104
|
+
.option('--format <fmt>', 'Output format: markdown, json, or both', 'both')
|
|
2105
|
+
.option('--max-gaps <n>', 'Maximum number of gaps to include', '50')
|
|
2106
|
+
.option('--priority <p>', 'Only include gaps at this priority or higher', 'P3')
|
|
2107
|
+
.action(async (options) => {
|
|
2108
|
+
const flows = await (0, index_4.exportAiFlows)({
|
|
2109
|
+
reportsDir: options.reportsDir,
|
|
2110
|
+
outDir: options.outDir,
|
|
2111
|
+
format: options.format,
|
|
2112
|
+
maxGaps: parseInt(options.maxGaps, 10),
|
|
2113
|
+
priority: options.priority,
|
|
2114
|
+
});
|
|
2115
|
+
console.log(`\nAI flows export complete:`);
|
|
2116
|
+
console.log(` Gaps exported: ${flows.gaps.length}`);
|
|
2117
|
+
console.log(` Project: ${flows.project.name}`);
|
|
2118
|
+
console.log(` Language: ${flows.project.language}`);
|
|
2119
|
+
});
|
|
2120
|
+
program
|
|
2121
|
+
.command('score-tests')
|
|
2122
|
+
.description('Score quality of existing test suite on 5 dimensions (0-100)')
|
|
2123
|
+
.option('--tests <glob>', 'Glob pattern for test files to score', 'tests/**/*.test.ts')
|
|
2124
|
+
.option('--reports-dir <dir>', 'Directory to write quality score output', 'reports/')
|
|
2125
|
+
.option('--fail-below <score>', 'Exit non-zero if any file scores below this', '0')
|
|
2126
|
+
.action(async (options) => {
|
|
2127
|
+
var _a;
|
|
2128
|
+
try {
|
|
2129
|
+
const report = await (0, index_4.scoreTests)({
|
|
2130
|
+
testsGlob: options.tests,
|
|
2131
|
+
reportsDir: options.reportsDir,
|
|
2132
|
+
failBelow: parseInt(options.failBelow, 10),
|
|
2133
|
+
});
|
|
2134
|
+
console.log(`\nTest Quality Score Report:`);
|
|
2135
|
+
console.log(` Overall score: ${report.overallScore}/100`);
|
|
2136
|
+
console.log(` Files scored: ${report.byFile.length}`);
|
|
2137
|
+
if (report.lowestQualityFiles.length > 0) {
|
|
2138
|
+
console.log(`\n Lowest quality files:`);
|
|
2139
|
+
for (const f of report.lowestQualityFiles) {
|
|
2140
|
+
const entry = report.byFile.find(b => b.file === f);
|
|
2141
|
+
console.log(` ${f}: ${(_a = entry === null || entry === void 0 ? void 0 : entry.score) !== null && _a !== void 0 ? _a : '?'}/100`);
|
|
2142
|
+
}
|
|
2143
|
+
}
|
|
2144
|
+
if (report.highestRiskLowQualityGaps.length > 0) {
|
|
2145
|
+
console.log(`\n High risk + low quality:`);
|
|
2146
|
+
for (const g of report.highestRiskLowQualityGaps) {
|
|
2147
|
+
console.log(` ${g.endpoint}: quality=${g.qualityScore}, risk=${g.riskScore}`);
|
|
2148
|
+
console.log(` → ${g.primaryIssue}`);
|
|
2149
|
+
}
|
|
2150
|
+
}
|
|
2151
|
+
console.log(`\n Report written to: ${options.reportsDir}/test-quality.json`);
|
|
2152
|
+
}
|
|
2153
|
+
catch (err) {
|
|
2154
|
+
if (err instanceof Error) {
|
|
2155
|
+
console.error(err.message);
|
|
2156
|
+
}
|
|
2157
|
+
process.exit(1);
|
|
2158
|
+
}
|
|
2159
|
+
});
|
|
2047
2160
|
// Parse the command-line arguments
|
|
2048
2161
|
program.parse(process.argv);
|
|
2049
2162
|
// When invoked with no arguments (no subcommand), display help
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"semanticBuilder.d.ts","sourceRoot":"","sources":["../../../../src/languages/java/semanticBuilder.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAEV,cAAc,EACd,gBAAgB,EAChB,gBAAgB,EAChB,iBAAiB,EACjB,eAAe,EACf,OAAO,EACR,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAKL,KAAK,MAAM,EACZ,MAAM,2BAA2B,CAAC;AAOnC,wBAAgB,kBAAkB,CAChC,IAAI,EAAE,MAAM,GACX;IAAE,SAAS,EAAE,GAAG,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;IAAC,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAA;CAAE,CAmErF;AAID,wBAAgB,oBAAoB,CAClC,IAAI,EAAE,MAAM,EACZ,SAAS,EAAE,GAAG,CAAC,MAAM,EAAE,cAAc,CAAC,GACrC,GAAG,CAAC,MAAM,EAAE,gBAAgB,CAAC,
|
|
1
|
+
{"version":3,"file":"semanticBuilder.d.ts","sourceRoot":"","sources":["../../../../src/languages/java/semanticBuilder.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAEV,cAAc,EACd,gBAAgB,EAChB,gBAAgB,EAChB,iBAAiB,EACjB,eAAe,EACf,OAAO,EACR,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAKL,KAAK,MAAM,EACZ,MAAM,2BAA2B,CAAC;AAOnC,wBAAgB,kBAAkB,CAChC,IAAI,EAAE,MAAM,GACX;IAAE,SAAS,EAAE,GAAG,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;IAAC,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAA;CAAE,CAmErF;AAID,wBAAgB,oBAAoB,CAClC,IAAI,EAAE,MAAM,EACZ,SAAS,EAAE,GAAG,CAAC,MAAM,EAAE,cAAc,CAAC,GACrC,GAAG,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAwC/B;AAID,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,MAAM,EACb,SAAS,EAAE,GAAG,CAAC,MAAM,EAAE,cAAc,CAAC,EACtC,GAAG,EAAE,gBAAgB,EAAE,GACtB,IAAI,CA+EN;AAID,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,iBAAiB,EAAE,CAyBvE;AAID,wBAAgB,2BAA2B,CAAC,IAAI,EAAE,MAAM,GAAG,eAAe,EAAE,CAa3E;AAED,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,EAAE,CAa3D"}
|
|
@@ -97,6 +97,8 @@ function extractJavaFunctions(root, constants) {
|
|
|
97
97
|
continue;
|
|
98
98
|
const annotations = extractAnnotationNames(method);
|
|
99
99
|
const block = (_e = (_d = method.childForFieldName) === null || _d === void 0 ? void 0 : _d.call(method, 'body')) !== null && _e !== void 0 ? _e : (0, treeSitterUtils_1.firstChildOfType)(method, 'block');
|
|
100
|
+
// Extract method parameters
|
|
101
|
+
const parameters = extractMethodParameters(method);
|
|
100
102
|
const bodyHttpCalls = [];
|
|
101
103
|
const calledFunctions = [];
|
|
102
104
|
let returnValue;
|
|
@@ -109,7 +111,7 @@ function extractJavaFunctions(root, constants) {
|
|
|
109
111
|
const cucumberPattern = extractCucumberPattern(annotations, method);
|
|
110
112
|
graph.set(name, {
|
|
111
113
|
name,
|
|
112
|
-
parameters
|
|
114
|
+
parameters,
|
|
113
115
|
bodyHttpCalls,
|
|
114
116
|
calledFunctions,
|
|
115
117
|
returnValue,
|
|
@@ -121,14 +123,44 @@ function extractJavaFunctions(root, constants) {
|
|
|
121
123
|
}
|
|
122
124
|
// ─── HTTP call extraction ─────────────────────────────────────────────────────
|
|
123
125
|
function extractJavaHttpCalls(block, constants, out) {
|
|
124
|
-
var _a, _b, _c, _d, _e, _f, _g;
|
|
126
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s;
|
|
125
127
|
const methodInvocations = (0, treeSitterUtils_1.findNodes)(block, ['method_invocation']);
|
|
126
128
|
for (const invoc of methodInvocations) {
|
|
127
129
|
const methodName = (_e = (_c = (_b = (_a = invoc.childForFieldName) === null || _a === void 0 ? void 0 : _a.call(invoc, 'name')) === null || _b === void 0 ? void 0 : _b.text) !== null && _c !== void 0 ? _c : (_d = firstChildNamed(invoc, 'identifier')) === null || _d === void 0 ? void 0 : _d.text) !== null && _e !== void 0 ? _e : '';
|
|
128
130
|
const lowerMethod = methodName.toLowerCase();
|
|
131
|
+
// MockMvc: perform(get("/path")) — extract the inner HTTP method call
|
|
132
|
+
if (lowerMethod === 'perform') {
|
|
133
|
+
const argList = (_g = (_f = invoc.childForFieldName) === null || _f === void 0 ? void 0 : _f.call(invoc, 'arguments')) !== null && _g !== void 0 ? _g : (0, treeSitterUtils_1.firstChildOfType)(invoc, 'argument_list');
|
|
134
|
+
if (!argList)
|
|
135
|
+
continue;
|
|
136
|
+
// The argument to perform() is a method invocation like get("/path") or post("/path")
|
|
137
|
+
const innerInvocations = (0, treeSitterUtils_1.findNodes)(argList, ['method_invocation']);
|
|
138
|
+
for (const innerInvoc of innerInvocations) {
|
|
139
|
+
const innerMethodName = (_m = (_k = (_j = (_h = innerInvoc.childForFieldName) === null || _h === void 0 ? void 0 : _h.call(innerInvoc, 'name')) === null || _j === void 0 ? void 0 : _j.text) !== null && _k !== void 0 ? _k : (_l = firstChildNamed(innerInvoc, 'identifier')) === null || _l === void 0 ? void 0 : _l.text) !== null && _m !== void 0 ? _m : '';
|
|
140
|
+
const innerLower = innerMethodName.toLowerCase();
|
|
141
|
+
if (!HTTP_METHODS.has(innerLower))
|
|
142
|
+
continue;
|
|
143
|
+
const innerArgList = (_p = (_o = innerInvoc.childForFieldName) === null || _o === void 0 ? void 0 : _o.call(innerInvoc, 'arguments')) !== null && _p !== void 0 ? _p : (0, treeSitterUtils_1.firstChildOfType)(innerInvoc, 'argument_list');
|
|
144
|
+
if (!innerArgList)
|
|
145
|
+
continue;
|
|
146
|
+
const innerStringArg = findFirstStringInArgList(innerArgList, constants);
|
|
147
|
+
if (!innerStringArg)
|
|
148
|
+
continue;
|
|
149
|
+
const normalizedPath = innerStringArg.value.startsWith('/') ? (0, resolvePaths_1.normalizePathToTemplate)(innerStringArg.value) : undefined;
|
|
150
|
+
out.push({
|
|
151
|
+
method: innerLower.toUpperCase(),
|
|
152
|
+
rawPathArg: (_q = innerStringArg.varName) !== null && _q !== void 0 ? _q : innerStringArg.value,
|
|
153
|
+
resolvedPath: innerStringArg.value,
|
|
154
|
+
normalizedPath,
|
|
155
|
+
resolutionType: innerStringArg.isDirect ? 'direct' : 'constant',
|
|
156
|
+
confidence: innerStringArg.isDirect ? 'high' : 'medium',
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
continue;
|
|
160
|
+
}
|
|
129
161
|
if (!HTTP_METHODS.has(lowerMethod))
|
|
130
162
|
continue;
|
|
131
|
-
const argList = (
|
|
163
|
+
const argList = (_s = (_r = invoc.childForFieldName) === null || _r === void 0 ? void 0 : _r.call(invoc, 'arguments')) !== null && _s !== void 0 ? _s : (0, treeSitterUtils_1.firstChildOfType)(invoc, 'argument_list');
|
|
132
164
|
if (!argList)
|
|
133
165
|
continue;
|
|
134
166
|
// Extract the first string argument (path)
|
|
@@ -138,15 +170,6 @@ function extractJavaHttpCalls(block, constants, out) {
|
|
|
138
170
|
const { value: path, isDirect, varName } = firstStringArg;
|
|
139
171
|
// Try to detect the HTTP method from context
|
|
140
172
|
let httpMethod = lowerMethod.toUpperCase();
|
|
141
|
-
// RestAssured: .when().get("/path") or .given().get("/path")
|
|
142
|
-
// The method name IS the HTTP method in RestAssured style
|
|
143
|
-
if (!HTTP_METHODS.has(lowerMethod))
|
|
144
|
-
continue;
|
|
145
|
-
// MockMvc: perform(get("/path")) — perform wraps a method call
|
|
146
|
-
if (lowerMethod === 'perform') {
|
|
147
|
-
// The arg is another method invocation
|
|
148
|
-
continue; // Handled when we process the inner get/post
|
|
149
|
-
}
|
|
150
173
|
if (lowerMethod === 'request') {
|
|
151
174
|
// generic request(method, path) — try to get HTTP method from first arg
|
|
152
175
|
const stringArgs = findAllStringsInArgList(argList, constants);
|
|
@@ -224,6 +247,40 @@ function extractJavaFlowRefs(root) {
|
|
|
224
247
|
return refs;
|
|
225
248
|
}
|
|
226
249
|
// ─── Helpers ──────────────────────────────────────────────────────────────────
|
|
250
|
+
/**
|
|
251
|
+
* Extract method parameters with their annotations (e.g. @RequestParam, @PathVariable, @RequestBody).
|
|
252
|
+
*/
|
|
253
|
+
function extractMethodParameters(method) {
|
|
254
|
+
var _a;
|
|
255
|
+
const params = [];
|
|
256
|
+
const formalParams = (0, treeSitterUtils_1.firstChildOfType)(method, 'formal_parameters');
|
|
257
|
+
if (!formalParams)
|
|
258
|
+
return params;
|
|
259
|
+
const paramNodes = (0, treeSitterUtils_1.findNodes)(formalParams, ['formal_parameter', 'spread_parameter']);
|
|
260
|
+
for (const paramNode of paramNodes) {
|
|
261
|
+
const paramAnnotations = [];
|
|
262
|
+
(0, treeSitterUtils_1.walkTree)(paramNode, (n) => {
|
|
263
|
+
var _a;
|
|
264
|
+
if (n.type === 'annotation' || n.type === 'marker_annotation') {
|
|
265
|
+
const nameNode = (0, treeSitterUtils_1.firstChildOfType)(n, 'identifier');
|
|
266
|
+
if (nameNode)
|
|
267
|
+
paramAnnotations.push('@' + ((_a = nameNode.text) !== null && _a !== void 0 ? _a : ''));
|
|
268
|
+
}
|
|
269
|
+
});
|
|
270
|
+
const nameNode = firstChildNamed(paramNode, 'identifier');
|
|
271
|
+
const name = (_a = nameNode === null || nameNode === void 0 ? void 0 : nameNode.text) !== null && _a !== void 0 ? _a : '';
|
|
272
|
+
if (!name)
|
|
273
|
+
continue;
|
|
274
|
+
// Include annotation prefix for annotated params (Spring @RequestParam, @PathVariable, etc.)
|
|
275
|
+
if (paramAnnotations.length > 0) {
|
|
276
|
+
params.push(`${paramAnnotations.join(' ')} ${name}`);
|
|
277
|
+
}
|
|
278
|
+
else {
|
|
279
|
+
params.push(name);
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
return params;
|
|
283
|
+
}
|
|
227
284
|
function extractModifierTexts(node) {
|
|
228
285
|
const modifiers = [];
|
|
229
286
|
(0, treeSitterUtils_1.walkTree)(node, (n) => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"angularDetector.d.ts","sourceRoot":"","sources":["../../../../src/languages/javascript/angularDetector.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,kBAAkB,EAAE,OAAO,CAAC;IAC5B,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,gBAAgB;IAC/B,wCAAwC;IACxC,aAAa,EAAE,MAAM,CAAC;IACtB,mCAAmC;IACnC,YAAY,EAAE,MAAM,CAAC;IACrB,+DAA+D;IAC/D,KAAK,EAAE,aAAa,GAAG,WAAW,CAAC;IACnC,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,YAAY,GAAG,aAAa,CAAC;IACnC,SAAS,EAAE,aAAa,GAAG,kBAAkB,GAAG,eAAe,GAAG,SAAS,GAAG,UAAU,CAAC;IACzF,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,aAAa,GAAG,YAAY,CAAC;IACnC,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,gBAAgB;IAC/B,2BAA2B,EAAE,OAAO,CAAC;IACrC,oBAAoB,EAAE,MAAM,EAAE,CAAC;IAC/B,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,eAAe,EAAE,CAyC9F;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,gBAAgB,EAAE,
|
|
1
|
+
{"version":3,"file":"angularDetector.d.ts","sourceRoot":"","sources":["../../../../src/languages/javascript/angularDetector.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,kBAAkB,EAAE,OAAO,CAAC;IAC5B,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,gBAAgB;IAC/B,wCAAwC;IACxC,aAAa,EAAE,MAAM,CAAC;IACtB,mCAAmC;IACnC,YAAY,EAAE,MAAM,CAAC;IACrB,+DAA+D;IAC/D,KAAK,EAAE,aAAa,GAAG,WAAW,CAAC;IACnC,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,YAAY,GAAG,aAAa,CAAC;IACnC,SAAS,EAAE,aAAa,GAAG,kBAAkB,GAAG,eAAe,GAAG,SAAS,GAAG,UAAU,CAAC;IACzF,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,aAAa,GAAG,YAAY,CAAC;IACnC,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,gBAAgB;IAC/B,2BAA2B,EAAE,OAAO,CAAC;IACrC,oBAAoB,EAAE,MAAM,EAAE,CAAC;IAC/B,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,eAAe,EAAE,CAyC9F;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,gBAAgB,EAAE,CA2EhG;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,YAAY,EAAE,CAyCxF;AAED;;GAEG;AACH,wBAAgB,yBAAyB,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,kBAAkB,EAAE,CAgCpG;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,gBAAgB,CAY7F;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAEhE"}
|
|
@@ -68,33 +68,66 @@ function detectAngularInjections(sourceText, filePath) {
|
|
|
68
68
|
const injections = [];
|
|
69
69
|
const lines = sourceText.split('\n');
|
|
70
70
|
let currentClass = '';
|
|
71
|
+
let currentConstHost = '';
|
|
72
|
+
let inConstructorParams = false;
|
|
71
73
|
for (let i = 0; i < lines.length; i++) {
|
|
72
74
|
const line = lines[i];
|
|
73
75
|
// Track current class
|
|
74
76
|
const classMatch = line.match(/class\s+(\w+)/);
|
|
75
77
|
if (classMatch)
|
|
76
78
|
currentClass = classMatch[1];
|
|
79
|
+
// Track current const/export const assignment as potential host for inject() outside class.
|
|
80
|
+
// Only update when the line is NOT itself an inject() call (e.g. skip `const x = inject(Y)`).
|
|
81
|
+
if (!currentClass) {
|
|
82
|
+
const constHostMatch = line.match(/(?:export\s+)?(?:const|let)\s+(\w+)\s*(?::\s*\S+)?\s*=/);
|
|
83
|
+
if (constHostMatch && !line.match(/=\s*inject\s*\(/)) {
|
|
84
|
+
currentConstHost = constHostMatch[1];
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
// Track constructor parameter block boundaries
|
|
88
|
+
if (/\bconstructor\s*\(/.test(line)) {
|
|
89
|
+
inConstructorParams = true;
|
|
90
|
+
}
|
|
91
|
+
if (inConstructorParams && line.includes(')')) {
|
|
92
|
+
// Process this line (it's still inside the constructor params), then close
|
|
93
|
+
// We'll close after checking for injections below
|
|
94
|
+
}
|
|
77
95
|
// Constructor injection: constructor(private http: HttpClient)
|
|
78
|
-
|
|
79
|
-
if (
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
96
|
+
// Only match visibility-modified parameters when inside a constructor(...) block
|
|
97
|
+
if (inConstructorParams) {
|
|
98
|
+
const ctorParamPattern = /(?:private|protected|public|readonly)\s+(\w+)\s*:\s*(\w+)/g;
|
|
99
|
+
let ctorMatch;
|
|
100
|
+
while ((ctorMatch = ctorParamPattern.exec(line)) !== null) {
|
|
101
|
+
if (currentClass) {
|
|
102
|
+
injections.push({
|
|
103
|
+
consumerClass: currentClass,
|
|
104
|
+
serviceClass: ctorMatch[2],
|
|
105
|
+
style: 'constructor',
|
|
106
|
+
sourceFile: filePath,
|
|
107
|
+
line: i + 1,
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
// Close the constructor param block after processing (handles closing paren on same line)
|
|
113
|
+
if (inConstructorParams && line.includes(')')) {
|
|
114
|
+
inConstructorParams = false;
|
|
87
115
|
}
|
|
88
116
|
// Functional inject: inject(HttpClient)
|
|
89
117
|
const injectMatch = line.match(/(\w+)\s*=\s*inject\s*\(\s*(\w+)\s*\)/);
|
|
90
|
-
if (injectMatch
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
118
|
+
if (injectMatch) {
|
|
119
|
+
// Use the enclosing class, or fall back to the enclosing const/export const host
|
|
120
|
+
// (e.g. functional guards/interceptors: `export const authGuard: CanActivateFn = ...`)
|
|
121
|
+
const hostName = currentClass || currentConstHost;
|
|
122
|
+
if (hostName) {
|
|
123
|
+
injections.push({
|
|
124
|
+
consumerClass: hostName,
|
|
125
|
+
serviceClass: injectMatch[2],
|
|
126
|
+
style: 'inject-fn',
|
|
127
|
+
sourceFile: filePath,
|
|
128
|
+
line: i + 1,
|
|
129
|
+
});
|
|
130
|
+
}
|
|
98
131
|
}
|
|
99
132
|
}
|
|
100
133
|
return injections;
|