api-tests-coverage 1.0.4 → 1.0.6

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 (63) hide show
  1. package/dist/dashboard/dist/assets/_basePickBy-CeCjvJWr.js +1 -0
  2. package/dist/dashboard/dist/assets/_baseUniq-DQMeOG5y.js +1 -0
  3. package/dist/dashboard/dist/assets/arc-BDIdECDJ.js +1 -0
  4. package/dist/dashboard/dist/assets/architectureDiagram-VXUJARFQ-D2t8Py1B.js +36 -0
  5. package/dist/dashboard/dist/assets/blockDiagram-VD42YOAC-7B2h6RPh.js +122 -0
  6. package/dist/dashboard/dist/assets/c4Diagram-YG6GDRKO-BJS73w81.js +10 -0
  7. package/dist/dashboard/dist/assets/channel-B5FEo6x8.js +1 -0
  8. package/dist/dashboard/dist/assets/chunk-4BX2VUAB-rMDV_g4i.js +1 -0
  9. package/dist/dashboard/dist/assets/chunk-55IACEB6-H2T0HHMf.js +1 -0
  10. package/dist/dashboard/dist/assets/chunk-B4BG7PRW-BIav900j.js +165 -0
  11. package/dist/dashboard/dist/assets/chunk-DI55MBZ5-CL1ZxZeg.js +220 -0
  12. package/dist/dashboard/dist/assets/chunk-FMBD7UC4-BH1h7N7Y.js +15 -0
  13. package/dist/dashboard/dist/assets/chunk-QN33PNHL-Dzk5VCZ3.js +1 -0
  14. package/dist/dashboard/dist/assets/chunk-QZHKN3VN-Z3uL3Vu6.js +1 -0
  15. package/dist/dashboard/dist/assets/chunk-TZMSLE5B-Bk8ko3-5.js +1 -0
  16. package/dist/dashboard/dist/assets/classDiagram-2ON5EDUG-M4p4DdHs.js +1 -0
  17. package/dist/dashboard/dist/assets/classDiagram-v2-WZHVMYZB-M4p4DdHs.js +1 -0
  18. package/dist/dashboard/dist/assets/clone-DISkn1y_.js +1 -0
  19. package/dist/dashboard/dist/assets/cose-bilkent-S5V4N54A-BbDNIhrI.js +1 -0
  20. package/dist/dashboard/dist/assets/dagre-6UL2VRFP-Niwmlwr0.js +4 -0
  21. package/dist/dashboard/dist/assets/diagram-PSM6KHXK-D6YSgDDJ.js +24 -0
  22. package/dist/dashboard/dist/assets/diagram-QEK2KX5R-BIV3o3EV.js +43 -0
  23. package/dist/dashboard/dist/assets/diagram-S2PKOQOG-B_V6T3Do.js +24 -0
  24. package/dist/dashboard/dist/assets/erDiagram-Q2GNP2WA-Dv8XSfJj.js +60 -0
  25. package/dist/dashboard/dist/assets/flowDiagram-NV44I4VS-DHVxWNFx.js +162 -0
  26. package/dist/dashboard/dist/assets/ganttDiagram-JELNMOA3-C0zKIcDh.js +267 -0
  27. package/dist/dashboard/dist/assets/gitGraphDiagram-V2S2FVAM-DbNQAtGz.js +65 -0
  28. package/dist/dashboard/dist/assets/graph-BUXAK8S4.js +1 -0
  29. package/dist/dashboard/dist/assets/index-HrRX8fCW.css +1 -0
  30. package/dist/dashboard/dist/assets/index-k7QMCdxo.js +522 -0
  31. package/dist/dashboard/dist/assets/infoDiagram-HS3SLOUP-CbvfFEOs.js +2 -0
  32. package/dist/dashboard/dist/assets/journeyDiagram-XKPGCS4Q-CHncp1wO.js +139 -0
  33. package/dist/dashboard/dist/assets/kanban-definition-3W4ZIXB7-Ct5tvLkE.js +89 -0
  34. package/dist/dashboard/dist/assets/layout-DEw3EHVd.js +1 -0
  35. package/dist/dashboard/dist/assets/mindmap-definition-VGOIOE7T-CM92aa9b.js +68 -0
  36. package/dist/dashboard/dist/assets/pieDiagram-ADFJNKIX-Dow8SBXC.js +30 -0
  37. package/dist/dashboard/dist/assets/quadrantDiagram-AYHSOK5B-CHDOoeNa.js +7 -0
  38. package/dist/dashboard/dist/assets/requirementDiagram-UZGBJVZJ-BdQwEiam.js +64 -0
  39. package/dist/dashboard/dist/assets/sankeyDiagram-TZEHDZUN-C2tgBc3h.js +10 -0
  40. package/dist/dashboard/dist/assets/sequenceDiagram-WL72ISMW-BJapitlJ.js +145 -0
  41. package/dist/dashboard/dist/assets/stateDiagram-FKZM4ZOC-CAMqhH5J.js +1 -0
  42. package/dist/dashboard/dist/assets/stateDiagram-v2-4FDKWEC3-DMcei2iB.js +1 -0
  43. package/dist/dashboard/dist/assets/timeline-definition-IT6M3QCI-CgZuzj68.js +61 -0
  44. package/dist/dashboard/dist/assets/treemap-GDKQZRPO-DISZoPlK.js +162 -0
  45. package/dist/dashboard/dist/assets/xychartDiagram-PRI3JC2R-WhBuJ91k.js +7 -0
  46. package/dist/dashboard/dist/index.html +2 -2
  47. package/dist/src/businessCoverage.d.ts.map +1 -1
  48. package/dist/src/businessCoverage.js +14 -1
  49. package/dist/src/index.js +429 -29
  50. package/dist/src/inference/businessRuleInference.d.ts +8 -0
  51. package/dist/src/inference/businessRuleInference.d.ts.map +1 -1
  52. package/dist/src/inference/businessRuleInference.js +52 -0
  53. package/dist/src/inference/routeInference.d.ts +50 -0
  54. package/dist/src/inference/routeInference.d.ts.map +1 -0
  55. package/dist/src/inference/routeInference.js +220 -0
  56. package/dist/src/inference/scanManifest.d.ts +35 -0
  57. package/dist/src/inference/scanManifest.d.ts.map +1 -0
  58. package/dist/src/inference/scanManifest.js +58 -0
  59. package/dist/src/integrationCoverage.d.ts.map +1 -1
  60. package/dist/src/integrationCoverage.js +13 -1
  61. package/dist/src/serveDashboard.d.ts.map +1 -1
  62. package/dist/src/serveDashboard.js +11 -0
  63. package/package.json +1 -1
@@ -0,0 +1,50 @@
1
+ /**
2
+ * Route Inference Engine
3
+ *
4
+ * Discovers HTTP routes from Express/Koa/Hapi/Fastify source files when no
5
+ * OpenAPI spec is available, enabling endpoint coverage analysis without
6
+ * a pre-authored specification.
7
+ *
8
+ * Patterns supported:
9
+ * - Express/Koa: router.get('/path', ...) / app.post('/path', ...)
10
+ * - Multi-line: router.get(\n '/path', ...) — path on next line
11
+ * - Chained: router.route('/path').get(...).post(...)
12
+ * - JSDoc route annotations: @route {GET} /path (used only when no code pattern found)
13
+ *
14
+ * Deduplication:
15
+ * - Routes are deduplicated by method:path within each file.
16
+ * - Actual code patterns take priority over JSDoc annotations.
17
+ */
18
+ export declare const HTTP_METHODS: readonly ["get", "post", "put", "patch", "delete", "head", "options"];
19
+ export type HttpMethod = typeof HTTP_METHODS[number];
20
+ export interface InferredRoute {
21
+ method: HttpMethod;
22
+ path: string;
23
+ /** Primary service function called in the route handler, if detectable */
24
+ handlerFunction?: string;
25
+ sourceFile: string;
26
+ lineNumber: number;
27
+ /** How this route was discovered */
28
+ discoveredVia: 'code' | 'jsdoc';
29
+ }
30
+ export interface RouteInferenceResult {
31
+ routes: InferredRoute[];
32
+ filesAnalyzed: number;
33
+ warnings: string[];
34
+ }
35
+ /**
36
+ * Infer routes from a single source file.
37
+ * Routes are deduplicated by method:path within the file.
38
+ * Code-based patterns take priority over JSDoc annotations for the same method+path.
39
+ */
40
+ export declare function inferRoutesFromFile(filePath: string): InferredRoute[];
41
+ /**
42
+ * Infer routes from a set of service source files.
43
+ */
44
+ export declare function inferRoutes(serviceFiles: string[]): RouteInferenceResult;
45
+ /**
46
+ * Write inferred routes to the reports directory.
47
+ * Returns the path of the written file.
48
+ */
49
+ export declare function writeInferredRoutes(result: RouteInferenceResult, reportsDir: string): string;
50
+ //# sourceMappingURL=routeInference.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"routeInference.d.ts","sourceRoot":"","sources":["../../../src/inference/routeInference.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAOH,eAAO,MAAM,YAAY,uEAAwE,CAAC;AAClG,MAAM,MAAM,UAAU,GAAG,OAAO,YAAY,CAAC,MAAM,CAAC,CAAC;AAErD,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,UAAU,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,0EAA0E;IAC1E,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,oCAAoC;IACpC,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC;CACjC;AAED,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,aAAa,EAAE,CAAC;IACxB,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAoDD;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,aAAa,EAAE,CAiFrE;AAiBD;;GAEG;AACH,wBAAgB,WAAW,CAAC,YAAY,EAAE,MAAM,EAAE,GAAG,oBAAoB,CAgBxE;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,oBAAoB,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,CAY5F"}
@@ -0,0 +1,220 @@
1
+ "use strict";
2
+ /**
3
+ * Route Inference Engine
4
+ *
5
+ * Discovers HTTP routes from Express/Koa/Hapi/Fastify source files when no
6
+ * OpenAPI spec is available, enabling endpoint coverage analysis without
7
+ * a pre-authored specification.
8
+ *
9
+ * Patterns supported:
10
+ * - Express/Koa: router.get('/path', ...) / app.post('/path', ...)
11
+ * - Multi-line: router.get(\n '/path', ...) — path on next line
12
+ * - Chained: router.route('/path').get(...).post(...)
13
+ * - JSDoc route annotations: @route {GET} /path (used only when no code pattern found)
14
+ *
15
+ * Deduplication:
16
+ * - Routes are deduplicated by method:path within each file.
17
+ * - Actual code patterns take priority over JSDoc annotations.
18
+ */
19
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
20
+ if (k2 === undefined) k2 = k;
21
+ var desc = Object.getOwnPropertyDescriptor(m, k);
22
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
23
+ desc = { enumerable: true, get: function() { return m[k]; } };
24
+ }
25
+ Object.defineProperty(o, k2, desc);
26
+ }) : (function(o, m, k, k2) {
27
+ if (k2 === undefined) k2 = k;
28
+ o[k2] = m[k];
29
+ }));
30
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
31
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
32
+ }) : function(o, v) {
33
+ o["default"] = v;
34
+ });
35
+ var __importStar = (this && this.__importStar) || (function () {
36
+ var ownKeys = function(o) {
37
+ ownKeys = Object.getOwnPropertyNames || function (o) {
38
+ var ar = [];
39
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
40
+ return ar;
41
+ };
42
+ return ownKeys(o);
43
+ };
44
+ return function (mod) {
45
+ if (mod && mod.__esModule) return mod;
46
+ var result = {};
47
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
48
+ __setModuleDefault(result, mod);
49
+ return result;
50
+ };
51
+ })();
52
+ Object.defineProperty(exports, "__esModule", { value: true });
53
+ exports.HTTP_METHODS = void 0;
54
+ exports.inferRoutesFromFile = inferRoutesFromFile;
55
+ exports.inferRoutes = inferRoutes;
56
+ exports.writeInferredRoutes = writeInferredRoutes;
57
+ const fs = __importStar(require("fs"));
58
+ const path = __importStar(require("path"));
59
+ // ─── Public types ─────────────────────────────────────────────────────────────
60
+ exports.HTTP_METHODS = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options'];
61
+ // ─── Patterns ─────────────────────────────────────────────────────────────────
62
+ /** Matches: router.get('/path', ...) or app.post('/path', ...) — on a single line */
63
+ const ROUTER_METHOD_INLINE = /(?:router|app|server)\s*\.\s*(get|post|put|patch|delete|head|options)\s*\(\s*['"`]([^'"`]+)['"`]/i;
64
+ /**
65
+ * Matches the beginning of a router.method( call that spans multiple lines.
66
+ * Group 1 = method name (get|post|...).
67
+ * The route path is expected on the same or next line.
68
+ */
69
+ const ROUTER_METHOD_MULTILINE_START = /(?:router|app|server)\s*\.\s*(get|post|put|patch|delete|head|options)\s*\(\s*$/i;
70
+ /** Matches a standalone route path string (first arg in multi-line route) */
71
+ const ROUTE_PATH_LINE = /^\s*['"`]([^'"`]+)['"`]\s*,?\s*$/;
72
+ /** Matches: router.route('/path').get(...) — chained route definition */
73
+ const CHAINED_ROUTE_PATTERN = /(?:router|app)\s*\.\s*route\s*\(\s*['"`]([^'"`]+)['"`]\s*\)/i;
74
+ const CHAINED_METHOD_PATTERN = /\.\s*(get|post|put|patch|delete|head|options)\s*\(/gi;
75
+ /** Matches JSDoc @route {GET} /path */
76
+ const JSDOC_ROUTE_PATTERN = /@route\s+\{(GET|POST|PUT|PATCH|DELETE|HEAD|OPTIONS)\}\s+(\S+)/i;
77
+ /**
78
+ * Matches the primary async service function call within a route handler body.
79
+ * e.g. `await deleteComment(...)` or `const result = await getArticles(...)`.
80
+ * Group 1 = function name.
81
+ *
82
+ * Note: This only detects `await`-based async calls. Synchronous handlers
83
+ * (e.g. `res.json(getUsers())`) are not matched by this pattern.
84
+ */
85
+ const HANDLER_FUNCTION_PATTERN = /(?:await|const\s+\w+\s*=\s*await)\s+([a-zA-Z][a-zA-Z0-9]*)\s*\(/;
86
+ /**
87
+ * Number of source lines scanned ahead to find the primary handler function
88
+ * when the route is defined on a single line (router.method('/path', ...)).
89
+ * The inline form starts the handler function close to the route definition.
90
+ */
91
+ const HANDLER_SCAN_WINDOW_INLINE = 20;
92
+ /**
93
+ * Number of source lines scanned ahead to find the primary handler function
94
+ * when the route is defined with the path on the next line. The multi-line
95
+ * form has more preamble (middleware, auth, etc.) before the handler function.
96
+ */
97
+ const HANDLER_SCAN_WINDOW_MULTILINE = 25;
98
+ // ─── Core inference function ──────────────────────────────────────────────────
99
+ /**
100
+ * Infer routes from a single source file.
101
+ * Routes are deduplicated by method:path within the file.
102
+ * Code-based patterns take priority over JSDoc annotations for the same method+path.
103
+ */
104
+ function inferRoutesFromFile(filePath) {
105
+ let content;
106
+ try {
107
+ content = fs.readFileSync(filePath, 'utf-8');
108
+ }
109
+ catch {
110
+ return [];
111
+ }
112
+ const lines = content.split('\n');
113
+ // key = "method:path" → route (code-found routes win over jsdoc)
114
+ const byKey = new Map();
115
+ const addRoute = (method, routePath, lineNumber, discoveredVia, handlerFunction) => {
116
+ const key = `${method}:${routePath}`;
117
+ const existing = byKey.get(key);
118
+ // Prefer code-discovered over jsdoc; if same source, first occurrence wins
119
+ if (!existing || (discoveredVia === 'code' && existing.discoveredVia === 'jsdoc')) {
120
+ byKey.set(key, { method, path: routePath, handlerFunction, sourceFile: filePath, lineNumber, discoveredVia });
121
+ }
122
+ };
123
+ for (let lineIdx = 0; lineIdx < lines.length; lineIdx++) {
124
+ const line = lines[lineIdx];
125
+ // 1a. router.method('/path', ...) — all on one line
126
+ const inlineMatch = line.match(ROUTER_METHOD_INLINE);
127
+ if (inlineMatch) {
128
+ const method = inlineMatch[1].toLowerCase();
129
+ const routePath = inlineMatch[2];
130
+ // Scan up to HANDLER_SCAN_WINDOW_INLINE following lines for the primary await function call
131
+ const handlerFn = findHandlerFunction(lines, lineIdx, HANDLER_SCAN_WINDOW_INLINE);
132
+ addRoute(method, routePath, lineIdx + 1, 'code', handlerFn);
133
+ continue;
134
+ }
135
+ // 1b. router.method(\n '/path', ...) — method and path on separate lines
136
+ const multilineStart = line.match(ROUTER_METHOD_MULTILINE_START);
137
+ if (multilineStart && lineIdx + 1 < lines.length) {
138
+ const nextLine = lines[lineIdx + 1];
139
+ const pathMatch = nextLine.match(ROUTE_PATH_LINE);
140
+ if (pathMatch) {
141
+ const method = multilineStart[1].toLowerCase();
142
+ const routePath = pathMatch[1];
143
+ const handlerFn = findHandlerFunction(lines, lineIdx, HANDLER_SCAN_WINDOW_MULTILINE);
144
+ addRoute(method, routePath, lineIdx + 1, 'code', handlerFn);
145
+ lineIdx++; // skip the path line
146
+ continue;
147
+ }
148
+ }
149
+ // 2. JSDoc @route annotation (only added if no code pattern found for same route)
150
+ const jsDocMatch = line.match(JSDOC_ROUTE_PATTERN);
151
+ if (jsDocMatch) {
152
+ const method = jsDocMatch[1].toLowerCase();
153
+ const routePath = jsDocMatch[2];
154
+ addRoute(method, routePath, lineIdx + 1, 'jsdoc');
155
+ continue;
156
+ }
157
+ // 3. Chained: .route('/path').get(...).post(...)
158
+ const chainedPathMatch = line.match(CHAINED_ROUTE_PATTERN);
159
+ if (chainedPathMatch) {
160
+ const routePath = chainedPathMatch[1];
161
+ const windowEnd = Math.min(lineIdx + 5, lines.length);
162
+ const windowText = lines.slice(lineIdx, windowEnd).join(' ');
163
+ let methodMatch;
164
+ CHAINED_METHOD_PATTERN.lastIndex = 0;
165
+ while ((methodMatch = CHAINED_METHOD_PATTERN.exec(windowText)) !== null) {
166
+ const method = methodMatch[1].toLowerCase();
167
+ addRoute(method, routePath, lineIdx + 1, 'code');
168
+ }
169
+ }
170
+ }
171
+ return [...byKey.values()];
172
+ }
173
+ /**
174
+ * Scan ahead in the source lines from `startLine` to find the first awaited
175
+ * service function call in the route handler body.
176
+ */
177
+ function findHandlerFunction(lines, startLine, maxLines) {
178
+ const end = Math.min(startLine + maxLines, lines.length);
179
+ for (let i = startLine; i < end; i++) {
180
+ const m = lines[i].match(HANDLER_FUNCTION_PATTERN);
181
+ if (m)
182
+ return m[1];
183
+ }
184
+ return undefined;
185
+ }
186
+ // ─── Public API ───────────────────────────────────────────────────────────────
187
+ /**
188
+ * Infer routes from a set of service source files.
189
+ */
190
+ function inferRoutes(serviceFiles) {
191
+ const allRoutes = [];
192
+ const warnings = [];
193
+ let filesAnalyzed = 0;
194
+ for (const fp of serviceFiles) {
195
+ const fileRoutes = inferRoutesFromFile(fp);
196
+ allRoutes.push(...fileRoutes);
197
+ filesAnalyzed++;
198
+ }
199
+ if (allRoutes.length === 0) {
200
+ warnings.push('No HTTP routes detected in service files.');
201
+ }
202
+ return { routes: allRoutes, filesAnalyzed, warnings };
203
+ }
204
+ /**
205
+ * Write inferred routes to the reports directory.
206
+ * Returns the path of the written file.
207
+ */
208
+ function writeInferredRoutes(result, reportsDir) {
209
+ fs.mkdirSync(reportsDir, { recursive: true });
210
+ const outputPath = path.join(reportsDir, 'inferred-routes.json');
211
+ const output = {
212
+ generated_at: new Date().toISOString(),
213
+ route_source: 'inferred',
214
+ files_analyzed: result.filesAnalyzed,
215
+ route_count: result.routes.length,
216
+ routes: result.routes,
217
+ };
218
+ fs.writeFileSync(outputPath, JSON.stringify(output, null, 2), 'utf-8');
219
+ return outputPath;
220
+ }
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Scan Manifest
3
+ *
4
+ * Records what was scanned during a zero-config `analyze` run —
5
+ * files analyzed, languages detected, frameworks detected, and
6
+ * per-metric coverage outcomes with their source (explicit / inferred / skipped).
7
+ *
8
+ * Written to: reports/scan-manifest.json
9
+ */
10
+ export interface ScanTypeEntry {
11
+ type: string;
12
+ source: 'explicit' | 'inferred' | 'skipped';
13
+ reason?: string;
14
+ itemsFound: number;
15
+ itemsCovered: number;
16
+ coveragePercent: number;
17
+ }
18
+ export interface ScanManifest {
19
+ projectRoot: string;
20
+ analyzedAt: string;
21
+ discoveredFiles: {
22
+ serviceFiles: string[];
23
+ testFiles: string[];
24
+ specFiles: string[];
25
+ };
26
+ languages: string[];
27
+ frameworks: string[];
28
+ scanTypes: ScanTypeEntry[];
29
+ }
30
+ /**
31
+ * Write a scan manifest to the reports directory.
32
+ * Returns the path of the written file.
33
+ */
34
+ export declare function writeScanManifest(manifest: ScanManifest, reportsDir: string): string;
35
+ //# sourceMappingURL=scanManifest.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scanManifest.d.ts","sourceRoot":"","sources":["../../../src/inference/scanManifest.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAOH,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,UAAU,GAAG,UAAU,GAAG,SAAS,CAAC;IAC5C,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,eAAe,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,YAAY;IAC3B,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,eAAe,EAAE;QACf,YAAY,EAAE,MAAM,EAAE,CAAC;QACvB,SAAS,EAAE,MAAM,EAAE,CAAC;QACpB,SAAS,EAAE,MAAM,EAAE,CAAC;KACrB,CAAC;IACF,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,SAAS,EAAE,aAAa,EAAE,CAAC;CAC5B;AAID;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,CAKpF"}
@@ -0,0 +1,58 @@
1
+ "use strict";
2
+ /**
3
+ * Scan Manifest
4
+ *
5
+ * Records what was scanned during a zero-config `analyze` run —
6
+ * files analyzed, languages detected, frameworks detected, and
7
+ * per-metric coverage outcomes with their source (explicit / inferred / skipped).
8
+ *
9
+ * Written to: reports/scan-manifest.json
10
+ */
11
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
12
+ if (k2 === undefined) k2 = k;
13
+ var desc = Object.getOwnPropertyDescriptor(m, k);
14
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
15
+ desc = { enumerable: true, get: function() { return m[k]; } };
16
+ }
17
+ Object.defineProperty(o, k2, desc);
18
+ }) : (function(o, m, k, k2) {
19
+ if (k2 === undefined) k2 = k;
20
+ o[k2] = m[k];
21
+ }));
22
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
23
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
24
+ }) : function(o, v) {
25
+ o["default"] = v;
26
+ });
27
+ var __importStar = (this && this.__importStar) || (function () {
28
+ var ownKeys = function(o) {
29
+ ownKeys = Object.getOwnPropertyNames || function (o) {
30
+ var ar = [];
31
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
32
+ return ar;
33
+ };
34
+ return ownKeys(o);
35
+ };
36
+ return function (mod) {
37
+ if (mod && mod.__esModule) return mod;
38
+ var result = {};
39
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
40
+ __setModuleDefault(result, mod);
41
+ return result;
42
+ };
43
+ })();
44
+ Object.defineProperty(exports, "__esModule", { value: true });
45
+ exports.writeScanManifest = writeScanManifest;
46
+ const fs = __importStar(require("fs"));
47
+ const path = __importStar(require("path"));
48
+ // ─── Writer ───────────────────────────────────────────────────────────────────
49
+ /**
50
+ * Write a scan manifest to the reports directory.
51
+ * Returns the path of the written file.
52
+ */
53
+ function writeScanManifest(manifest, reportsDir) {
54
+ fs.mkdirSync(reportsDir, { recursive: true });
55
+ const outputPath = path.join(reportsDir, 'scan-manifest.json');
56
+ fs.writeFileSync(outputPath, JSON.stringify(manifest, null, 2), 'utf-8');
57
+ return outputPath;
58
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"integrationCoverage.d.ts","sourceRoot":"","sources":["../../src/integrationCoverage.ts"],"names":[],"mappings":"AAOA,MAAM,MAAM,YAAY,GAAG,KAAK,GAAG,OAAO,GAAG,UAAU,CAAC;AAExD,MAAM,WAAW,QAAQ;IACvB,2CAA2C;IAC3C,EAAE,EAAE,MAAM,CAAC;IACX,wDAAwD;IACxD,WAAW,EAAE,MAAM,CAAC;IACpB,iFAAiF;IACjF,IAAI,CAAC,EAAE,YAAY,CAAC;IACpB,iDAAiD;IACjD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,sDAAsD;IACtD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;OAGG;IACH,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,MAAM,WAAW,eAAe;IAC9B,qCAAqC;IACrC,EAAE,EAAE,MAAM,CAAC;IACX,6CAA6C;IAC7C,IAAI,EAAE,MAAM,CAAC;IACb,+DAA+D;IAC/D,WAAW,EAAE,MAAM,CAAC;IACpB,uDAAuD;IACvD,KAAK,EAAE,QAAQ,EAAE,CAAC;CACnB;AAED,MAAM,WAAW,oBAAoB;IACnC,KAAK,EAAE,eAAe,EAAE,CAAC;CAC1B;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,QAAQ,CAAC;IACf,OAAO,EAAE,OAAO,CAAC;IACjB,YAAY,EAAE,MAAM,EAAE,CAAC;CACxB;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,eAAe,CAAC;IACtB,kGAAkG;IAClG,MAAM,EAAE,UAAU,GAAG,SAAS,GAAG,SAAS,CAAC;IAC3C,wEAAwE;IACxE,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,+CAA+C;IAC/C,KAAK,EAAE,YAAY,EAAE,CAAC;CACvB;AAED,MAAM,WAAW,yBAAyB;IACxC,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,YAAY,EAAE,CAAC;CACvB;AAID;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,SAAS,EAAE,MAAM,GAAG,eAAe,EAAE,CAsB1E;AAkFD;;;GAGG;AACH,wBAAsB,0BAA0B,CAC9C,KAAK,EAAE,eAAe,EAAE,EACxB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,YAAY,EAAE,CAAC,CAqDzB;AAID;;GAEG;AACH,wBAAgB,8BAA8B,CAC5C,SAAS,EAAE,YAAY,EAAE,GACxB,yBAAyB,CAQ3B;AAID;;GAEG;AACH,wBAAgB,0BAA0B,CACxC,MAAM,EAAE,yBAAyB,EACjC,UAAU,EAAE,MAAM,GACjB,IAAI,CAgIN"}
1
+ {"version":3,"file":"integrationCoverage.d.ts","sourceRoot":"","sources":["../../src/integrationCoverage.ts"],"names":[],"mappings":"AAOA,MAAM,MAAM,YAAY,GAAG,KAAK,GAAG,OAAO,GAAG,UAAU,CAAC;AAExD,MAAM,WAAW,QAAQ;IACvB,2CAA2C;IAC3C,EAAE,EAAE,MAAM,CAAC;IACX,wDAAwD;IACxD,WAAW,EAAE,MAAM,CAAC;IACpB,iFAAiF;IACjF,IAAI,CAAC,EAAE,YAAY,CAAC;IACpB,iDAAiD;IACjD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,sDAAsD;IACtD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;OAGG;IACH,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,MAAM,WAAW,eAAe;IAC9B,qCAAqC;IACrC,EAAE,EAAE,MAAM,CAAC;IACX,6CAA6C;IAC7C,IAAI,EAAE,MAAM,CAAC;IACb,+DAA+D;IAC/D,WAAW,EAAE,MAAM,CAAC;IACpB,uDAAuD;IACvD,KAAK,EAAE,QAAQ,EAAE,CAAC;CACnB;AAED,MAAM,WAAW,oBAAoB;IACnC,KAAK,EAAE,eAAe,EAAE,CAAC;CAC1B;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,QAAQ,CAAC;IACf,OAAO,EAAE,OAAO,CAAC;IACjB,YAAY,EAAE,MAAM,EAAE,CAAC;CACxB;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,eAAe,CAAC;IACtB,kGAAkG;IAClG,MAAM,EAAE,UAAU,GAAG,SAAS,GAAG,SAAS,CAAC;IAC3C,wEAAwE;IACxE,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,+CAA+C;IAC/C,KAAK,EAAE,YAAY,EAAE,CAAC;CACvB;AAED,MAAM,WAAW,yBAAyB;IACxC,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,YAAY,EAAE,CAAC;CACvB;AAID;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,SAAS,EAAE,MAAM,GAAG,eAAe,EAAE,CA4B1E;AAkFD;;;GAGG;AACH,wBAAsB,0BAA0B,CAC9C,KAAK,EAAE,eAAe,EAAE,EACxB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,YAAY,EAAE,CAAC,CAqDzB;AAID;;GAEG;AACH,wBAAgB,8BAA8B,CAC5C,SAAS,EAAE,YAAY,EAAE,GACxB,yBAAyB,CAQ3B;AAID;;GAEG;AACH,wBAAgB,0BAA0B,CACxC,MAAM,EAAE,yBAAyB,EACjC,UAAU,EAAE,MAAM,GACjB,IAAI,CAgIN"}
@@ -64,7 +64,19 @@ function parseIntegrationFlows(flowsPath) {
64
64
  !Array.isArray(parsed.flows)) {
65
65
  throw new Error(`Invalid integration flows file: expected a top-level "flows" array in ${flowsPath}`);
66
66
  }
67
- return parsed.flows;
67
+ return parsed.flows.map((flow) => {
68
+ var _a;
69
+ return ({
70
+ ...flow,
71
+ steps: ((_a = flow.steps) !== null && _a !== void 0 ? _a : []).map((step) => {
72
+ var _a;
73
+ return ({
74
+ ...step,
75
+ keywords: (_a = step.keywords) !== null && _a !== void 0 ? _a : [],
76
+ });
77
+ }),
78
+ });
79
+ });
68
80
  }
69
81
  /**
70
82
  * Extract all test/it declarations from a file, together with their
@@ -1 +1 @@
1
- {"version":3,"file":"serveDashboard.d.ts","sourceRoot":"","sources":["../../src/serveDashboard.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAwD7B,MAAM,WAAW,qBAAqB;IACpC,yEAAyE;IACzE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,uCAAuC;IACvC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,qDAAqD;IACrD,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAED;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAAC,OAAO,GAAE,qBAA0B,GAAG,IAAI,CAAC,MAAM,CAkF/E"}
1
+ {"version":3,"file":"serveDashboard.d.ts","sourceRoot":"","sources":["../../src/serveDashboard.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAwD7B,MAAM,WAAW,qBAAqB;IACpC,yEAAyE;IACzE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,uCAAuC;IACvC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,qDAAqD;IACrD,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAED;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAAC,OAAO,GAAE,qBAA0B,GAAG,IAAI,CAAC,MAAM,CA6F/E"}
@@ -165,6 +165,17 @@ function serveDashboard(options = {}) {
165
165
  }
166
166
  }
167
167
  });
168
+ server.on('error', (err) => {
169
+ if (err.code === 'EADDRINUSE') {
170
+ console.error(`\n[ERROR] Port ${port} is already in use.`);
171
+ console.error(` Kill the existing process or use --port <number> to choose a different port.`);
172
+ console.error(` Example: api-tests-coverage analyze --dashboard --port 4001 --open`);
173
+ }
174
+ else {
175
+ console.error(`\n[ERROR] Dashboard server failed to start: ${err.message}`);
176
+ }
177
+ process.exit(1);
178
+ });
168
179
  server.listen(port, () => {
169
180
  const serverUrl = `http://localhost:${port}`;
170
181
  console.log(`\n=== API Coverage Dashboard ===`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "api-tests-coverage",
3
- "version": "1.0.4",
3
+ "version": "1.0.6",
4
4
  "description": "CLI and library to measure how thoroughly your test suite exercises your API surface area",
5
5
  "main": "dist/src/lib/index.js",
6
6
  "types": "dist/src/lib/index.d.ts",