api-tests-coverage 1.0.0 → 1.0.2

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 (163) hide show
  1. package/dist/dashboard/assets/_basePickBy-DK6M9Uvz.js +1 -0
  2. package/dist/dashboard/assets/_baseUniq-BPCxdwlX.js +1 -0
  3. package/dist/dashboard/assets/arc-225azWF8.js +1 -0
  4. package/dist/dashboard/assets/architectureDiagram-VXUJARFQ-BW9j-2rE.js +36 -0
  5. package/dist/dashboard/assets/blockDiagram-VD42YOAC-CcWyVh_8.js +122 -0
  6. package/dist/dashboard/assets/c4Diagram-YG6GDRKO-Bq0y8Ms0.js +10 -0
  7. package/dist/dashboard/assets/channel-CPmdNASe.js +1 -0
  8. package/dist/dashboard/assets/chunk-4BX2VUAB-BrlBx_h4.js +1 -0
  9. package/dist/dashboard/assets/chunk-55IACEB6-BTGWaOkw.js +1 -0
  10. package/dist/dashboard/assets/chunk-B4BG7PRW-B-3Me5OV.js +165 -0
  11. package/dist/dashboard/assets/chunk-DI55MBZ5-BLZCyXU3.js +220 -0
  12. package/dist/dashboard/assets/chunk-FMBD7UC4-Bm9KRQE1.js +15 -0
  13. package/dist/dashboard/assets/chunk-QN33PNHL-DtWoo2Hn.js +1 -0
  14. package/dist/dashboard/assets/chunk-QZHKN3VN-DfaeFdsW.js +1 -0
  15. package/dist/dashboard/assets/chunk-TZMSLE5B-CM7Di7Gz.js +1 -0
  16. package/dist/dashboard/assets/classDiagram-2ON5EDUG-DTSnWk0q.js +1 -0
  17. package/dist/dashboard/assets/classDiagram-v2-WZHVMYZB-DTSnWk0q.js +1 -0
  18. package/dist/dashboard/assets/clone-DiFVAewv.js +1 -0
  19. package/dist/dashboard/assets/cose-bilkent-S5V4N54A-CI6S9tNC.js +1 -0
  20. package/dist/dashboard/assets/cytoscape.esm-CyJtwmzi.js +331 -0
  21. package/dist/dashboard/assets/dagre-6UL2VRFP-CD25jMwx.js +4 -0
  22. package/dist/dashboard/assets/diagram-PSM6KHXK-B2ziHyX_.js +24 -0
  23. package/dist/dashboard/assets/diagram-QEK2KX5R-DpPMBb2T.js +43 -0
  24. package/dist/dashboard/assets/diagram-S2PKOQOG-BplBVLaZ.js +24 -0
  25. package/dist/dashboard/assets/erDiagram-Q2GNP2WA-C6Kdrqa_.js +60 -0
  26. package/dist/dashboard/assets/flowDiagram-NV44I4VS-CBo4bgv8.js +162 -0
  27. package/dist/dashboard/assets/ganttDiagram-JELNMOA3-DL8oIX3C.js +267 -0
  28. package/dist/dashboard/assets/gitGraphDiagram-V2S2FVAM-5oPGxe6l.js +65 -0
  29. package/dist/dashboard/assets/graph-DWVIsnRu.js +1 -0
  30. package/dist/dashboard/assets/index-B2mS1bcV.js +522 -0
  31. package/dist/dashboard/assets/index-DBTGeaha.css +1 -0
  32. package/dist/dashboard/assets/infoDiagram-HS3SLOUP-D-bnjqH3.js +2 -0
  33. package/dist/dashboard/assets/journeyDiagram-XKPGCS4Q-DkT7QyWQ.js +139 -0
  34. package/dist/dashboard/assets/kanban-definition-3W4ZIXB7-CSO8OAdK.js +89 -0
  35. package/dist/dashboard/assets/katex-O9d3_IXG.js +261 -0
  36. package/dist/dashboard/assets/layout-BRUlIe_x.js +1 -0
  37. package/dist/dashboard/assets/mindmap-definition-VGOIOE7T-DabWpbNO.js +68 -0
  38. package/dist/dashboard/assets/pieDiagram-ADFJNKIX-x6W4JfPL.js +30 -0
  39. package/dist/dashboard/assets/quadrantDiagram-AYHSOK5B-Cs_QHGFN.js +7 -0
  40. package/dist/dashboard/assets/requirementDiagram-UZGBJVZJ-Y6IeHRvx.js +64 -0
  41. package/dist/dashboard/assets/sankeyDiagram-TZEHDZUN-CZT51ITh.js +10 -0
  42. package/dist/dashboard/assets/sequenceDiagram-WL72ISMW-DyAQKRQ-.js +145 -0
  43. package/dist/dashboard/assets/stateDiagram-FKZM4ZOC-DeadfBBo.js +1 -0
  44. package/dist/dashboard/assets/stateDiagram-v2-4FDKWEC3-D58eQQQS.js +1 -0
  45. package/dist/dashboard/assets/timeline-definition-IT6M3QCI-DYmeeClO.js +61 -0
  46. package/dist/dashboard/assets/treemap-GDKQZRPO-CKPSdFAX.js +162 -0
  47. package/dist/dashboard/assets/xychartDiagram-PRI3JC2R-Ch7ZZyVX.js +7 -0
  48. package/dist/dashboard/dist/assets/_basePickBy-DK6M9Uvz.js +1 -0
  49. package/dist/dashboard/dist/assets/_basePickBy-P9JMLvtQ.js +1 -0
  50. package/dist/dashboard/dist/assets/_baseUniq-BLr5OOl5.js +1 -0
  51. package/dist/dashboard/dist/assets/_baseUniq-BPCxdwlX.js +1 -0
  52. package/dist/dashboard/dist/assets/arc-225azWF8.js +1 -0
  53. package/dist/dashboard/dist/assets/arc-FwwTLzl4.js +1 -0
  54. package/dist/dashboard/dist/assets/architectureDiagram-VXUJARFQ-BW9j-2rE.js +36 -0
  55. package/dist/dashboard/dist/assets/architectureDiagram-VXUJARFQ-C7QAcrIt.js +36 -0
  56. package/dist/dashboard/dist/assets/blockDiagram-VD42YOAC-BYvjSDpK.js +122 -0
  57. package/dist/dashboard/dist/assets/blockDiagram-VD42YOAC-CcWyVh_8.js +122 -0
  58. package/dist/dashboard/dist/assets/c4Diagram-YG6GDRKO-Bq0y8Ms0.js +10 -0
  59. package/dist/dashboard/dist/assets/c4Diagram-YG6GDRKO-dUTtO4_k.js +10 -0
  60. package/dist/dashboard/dist/assets/channel-CPmdNASe.js +1 -0
  61. package/dist/dashboard/dist/assets/channel-DRY_ja-e.js +1 -0
  62. package/dist/dashboard/dist/assets/chunk-4BX2VUAB-BrlBx_h4.js +1 -0
  63. package/dist/dashboard/dist/assets/chunk-4BX2VUAB-NmyQ9Lvf.js +1 -0
  64. package/dist/dashboard/dist/assets/chunk-55IACEB6-BTGWaOkw.js +1 -0
  65. package/dist/dashboard/dist/assets/chunk-55IACEB6-GAN8BMbh.js +1 -0
  66. package/dist/dashboard/dist/assets/chunk-B4BG7PRW-B-3Me5OV.js +165 -0
  67. package/dist/dashboard/dist/assets/chunk-B4BG7PRW-CKtaL90X.js +165 -0
  68. package/dist/dashboard/dist/assets/chunk-DI55MBZ5-BLZCyXU3.js +220 -0
  69. package/dist/dashboard/dist/assets/chunk-DI55MBZ5-GokZ0alw.js +220 -0
  70. package/dist/dashboard/dist/assets/chunk-FMBD7UC4-Bm9KRQE1.js +15 -0
  71. package/dist/dashboard/dist/assets/chunk-FMBD7UC4-D8tBTVUA.js +15 -0
  72. package/dist/dashboard/dist/assets/chunk-QN33PNHL-C59bvcTc.js +1 -0
  73. package/dist/dashboard/dist/assets/chunk-QN33PNHL-DtWoo2Hn.js +1 -0
  74. package/dist/dashboard/dist/assets/chunk-QZHKN3VN-DfaeFdsW.js +1 -0
  75. package/dist/dashboard/dist/assets/chunk-QZHKN3VN-E7ncuJVt.js +1 -0
  76. package/dist/dashboard/dist/assets/chunk-TZMSLE5B-BcLpi7P1.js +1 -0
  77. package/dist/dashboard/dist/assets/chunk-TZMSLE5B-CM7Di7Gz.js +1 -0
  78. package/dist/dashboard/dist/assets/classDiagram-2ON5EDUG-DTSnWk0q.js +1 -0
  79. package/dist/dashboard/dist/assets/classDiagram-2ON5EDUG-Dy8_C5lE.js +1 -0
  80. package/dist/dashboard/dist/assets/classDiagram-v2-WZHVMYZB-DTSnWk0q.js +1 -0
  81. package/dist/dashboard/dist/assets/classDiagram-v2-WZHVMYZB-Dy8_C5lE.js +1 -0
  82. package/dist/dashboard/dist/assets/clone-B0_qHCw2.js +1 -0
  83. package/dist/dashboard/dist/assets/clone-DiFVAewv.js +1 -0
  84. package/dist/dashboard/dist/assets/cose-bilkent-S5V4N54A-BYK-qqpA.js +1 -0
  85. package/dist/dashboard/dist/assets/cose-bilkent-S5V4N54A-CI6S9tNC.js +1 -0
  86. package/dist/dashboard/dist/assets/cytoscape.esm-CyJtwmzi.js +331 -0
  87. package/dist/dashboard/dist/assets/dagre-6UL2VRFP-CD25jMwx.js +4 -0
  88. package/dist/dashboard/dist/assets/dagre-6UL2VRFP-CNIXE38x.js +4 -0
  89. package/dist/dashboard/dist/assets/diagram-PSM6KHXK-B2ziHyX_.js +24 -0
  90. package/dist/dashboard/dist/assets/diagram-PSM6KHXK-Dza_WM04.js +24 -0
  91. package/dist/dashboard/dist/assets/diagram-QEK2KX5R-175MJwNN.js +43 -0
  92. package/dist/dashboard/dist/assets/diagram-QEK2KX5R-DpPMBb2T.js +43 -0
  93. package/dist/dashboard/dist/assets/diagram-S2PKOQOG-BplBVLaZ.js +24 -0
  94. package/dist/dashboard/dist/assets/diagram-S2PKOQOG-DpUYqpiH.js +24 -0
  95. package/dist/dashboard/dist/assets/erDiagram-Q2GNP2WA-C6Kdrqa_.js +60 -0
  96. package/dist/dashboard/dist/assets/erDiagram-Q2GNP2WA-YGhaTIGv.js +60 -0
  97. package/dist/dashboard/dist/assets/flowDiagram-NV44I4VS-CBo4bgv8.js +162 -0
  98. package/dist/dashboard/dist/assets/flowDiagram-NV44I4VS-D9XX51TY.js +162 -0
  99. package/dist/dashboard/dist/assets/ganttDiagram-JELNMOA3-BnlL2FL1.js +267 -0
  100. package/dist/dashboard/dist/assets/ganttDiagram-JELNMOA3-DL8oIX3C.js +267 -0
  101. package/dist/dashboard/dist/assets/gitGraphDiagram-V2S2FVAM-5oPGxe6l.js +65 -0
  102. package/dist/dashboard/dist/assets/gitGraphDiagram-V2S2FVAM-IqGQHaKk.js +65 -0
  103. package/dist/dashboard/dist/assets/graph-DOoKbdQ6.js +1 -0
  104. package/dist/dashboard/dist/assets/graph-DWVIsnRu.js +1 -0
  105. package/dist/dashboard/dist/assets/index-B2mS1bcV.js +522 -0
  106. package/dist/dashboard/dist/assets/index-CTnNA-vP.js +522 -0
  107. package/dist/dashboard/dist/assets/index-DBTGeaha.css +1 -0
  108. package/dist/dashboard/dist/assets/infoDiagram-HS3SLOUP-D-PYXUrg.js +2 -0
  109. package/dist/dashboard/dist/assets/infoDiagram-HS3SLOUP-D-bnjqH3.js +2 -0
  110. package/dist/dashboard/dist/assets/journeyDiagram-XKPGCS4Q-DIxnZShx.js +139 -0
  111. package/dist/dashboard/dist/assets/journeyDiagram-XKPGCS4Q-DkT7QyWQ.js +139 -0
  112. package/dist/dashboard/dist/assets/kanban-definition-3W4ZIXB7-CSO8OAdK.js +89 -0
  113. package/dist/dashboard/dist/assets/kanban-definition-3W4ZIXB7-DIQJ-dLy.js +89 -0
  114. package/dist/dashboard/dist/assets/katex-O9d3_IXG.js +261 -0
  115. package/dist/dashboard/dist/assets/layout-BRUlIe_x.js +1 -0
  116. package/dist/dashboard/dist/assets/layout-Dx_sC6cU.js +1 -0
  117. package/dist/dashboard/dist/assets/mindmap-definition-VGOIOE7T-BWOv2jfH.js +68 -0
  118. package/dist/dashboard/dist/assets/mindmap-definition-VGOIOE7T-DabWpbNO.js +68 -0
  119. package/dist/dashboard/dist/assets/pieDiagram-ADFJNKIX-B-ZMfN-z.js +30 -0
  120. package/dist/dashboard/dist/assets/pieDiagram-ADFJNKIX-x6W4JfPL.js +30 -0
  121. package/dist/dashboard/dist/assets/quadrantDiagram-AYHSOK5B-Cs_QHGFN.js +7 -0
  122. package/dist/dashboard/dist/assets/quadrantDiagram-AYHSOK5B-lHEZJOJ6.js +7 -0
  123. package/dist/dashboard/dist/assets/requirementDiagram-UZGBJVZJ-Dmgv7ZrT.js +64 -0
  124. package/dist/dashboard/dist/assets/requirementDiagram-UZGBJVZJ-Y6IeHRvx.js +64 -0
  125. package/dist/dashboard/dist/assets/sankeyDiagram-TZEHDZUN-CZT51ITh.js +10 -0
  126. package/dist/dashboard/dist/assets/sankeyDiagram-TZEHDZUN-DYnsmtzq.js +10 -0
  127. package/dist/dashboard/dist/assets/sequenceDiagram-WL72ISMW-Cp0y_3Co.js +145 -0
  128. package/dist/dashboard/dist/assets/sequenceDiagram-WL72ISMW-DyAQKRQ-.js +145 -0
  129. package/dist/dashboard/dist/assets/stateDiagram-FKZM4ZOC-CmJ3FBc_.js +1 -0
  130. package/dist/dashboard/dist/assets/stateDiagram-FKZM4ZOC-DeadfBBo.js +1 -0
  131. package/dist/dashboard/dist/assets/stateDiagram-v2-4FDKWEC3-D58eQQQS.js +1 -0
  132. package/dist/dashboard/dist/assets/stateDiagram-v2-4FDKWEC3-DBJHmcPu.js +1 -0
  133. package/dist/dashboard/dist/assets/timeline-definition-IT6M3QCI-CnYcftUT.js +61 -0
  134. package/dist/dashboard/dist/assets/timeline-definition-IT6M3QCI-DYmeeClO.js +61 -0
  135. package/dist/dashboard/dist/assets/treemap-GDKQZRPO-B-4BtJ8O.js +162 -0
  136. package/dist/dashboard/dist/assets/treemap-GDKQZRPO-CKPSdFAX.js +162 -0
  137. package/dist/dashboard/dist/assets/xychartDiagram-PRI3JC2R-Ch7ZZyVX.js +7 -0
  138. package/dist/dashboard/dist/assets/xychartDiagram-PRI3JC2R-jiOJ2YB4.js +7 -0
  139. package/dist/dashboard/dist/index.html +14 -0
  140. package/dist/dashboard/dist/reports/business-coverage.json +201 -0
  141. package/dist/dashboard/dist/reports/coverage-intelligence.json +728 -0
  142. package/dist/dashboard/dist/reports/coverage-summary.json +763 -0
  143. package/dist/dashboard/dist/reports/endpoint-coverage.json +336 -0
  144. package/dist/dashboard/dist/reports/error-coverage.json +367 -0
  145. package/dist/dashboard/dist/reports/missing-tests-recommendations.json +285 -0
  146. package/dist/dashboard/dist/reports/risk-prioritization.json +312 -0
  147. package/dist/dashboard/dist/reports/security-coverage.json +299 -0
  148. package/dist/dashboard/dist/vite.svg +1 -0
  149. package/dist/dashboard/index.html +14 -0
  150. package/dist/dashboard/reports/business-coverage.json +201 -0
  151. package/dist/dashboard/reports/coverage-intelligence.json +728 -0
  152. package/dist/dashboard/reports/coverage-summary.json +763 -0
  153. package/dist/dashboard/reports/endpoint-coverage.json +336 -0
  154. package/dist/dashboard/reports/error-coverage.json +367 -0
  155. package/dist/dashboard/reports/missing-tests-recommendations.json +285 -0
  156. package/dist/dashboard/reports/risk-prioritization.json +312 -0
  157. package/dist/dashboard/reports/security-coverage.json +299 -0
  158. package/dist/dashboard/vite.svg +1 -0
  159. package/dist/src/index.js +74 -4
  160. package/dist/src/serveDashboard.d.ts +30 -0
  161. package/dist/src/serveDashboard.d.ts.map +1 -0
  162. package/dist/src/serveDashboard.js +191 -0
  163. package/package.json +3 -2
@@ -0,0 +1,299 @@
1
+ {
2
+ "total": 27,
3
+ "covered": 7,
4
+ "percentage": 23.08,
5
+ "scanFindings": 0,
6
+ "categorySummary": {
7
+ "authentication": {
8
+ "total": 1,
9
+ "covered": 1
10
+ },
11
+ "authorization": {
12
+ "total": 13,
13
+ "covered": 0
14
+ },
15
+ "input-validation": {
16
+ "total": 11,
17
+ "covered": 5
18
+ },
19
+ "cryptography": {
20
+ "total": 1,
21
+ "covered": 0
22
+ },
23
+ "session-management": {
24
+ "total": 0,
25
+ "covered": 0
26
+ }
27
+ },
28
+ "controls": [
29
+ {
30
+ "id": "authentication:bearerAuth",
31
+ "category": "authentication",
32
+ "description": "Authentication via security scheme \"bearerAuth\" (http/bearer)",
33
+ "covered": true,
34
+ "matchedTests": [
35
+ "returns 401 when no token",
36
+ "returns 401 when no token provided",
37
+ "returns 401 for invalid token",
38
+ "returns 401 without auth"
39
+ ],
40
+ "coveredByScanReport": false
41
+ },
42
+ {
43
+ "id": "cryptography:https",
44
+ "category": "cryptography",
45
+ "description": "API servers include non-HTTPS URLs – cryptographic transport security may be missing",
46
+ "covered": false,
47
+ "matchedTests": [],
48
+ "coveredByScanReport": false
49
+ },
50
+ {
51
+ "id": "authorization:get:/wallets",
52
+ "category": "authorization",
53
+ "description": "Authorization check for GET /wallets",
54
+ "endpoint": "GET /wallets",
55
+ "covered": false,
56
+ "matchedTests": [],
57
+ "coveredByScanReport": false
58
+ },
59
+ {
60
+ "id": "authorization:post:/wallets",
61
+ "category": "authorization",
62
+ "description": "Authorization check for POST /wallets",
63
+ "endpoint": "POST /wallets",
64
+ "covered": false,
65
+ "matchedTests": [],
66
+ "coveredByScanReport": false
67
+ },
68
+ {
69
+ "id": "input-validation:post:/wallets",
70
+ "category": "input-validation",
71
+ "description": "Input validation for POST /wallets",
72
+ "endpoint": "POST /wallets",
73
+ "covered": true,
74
+ "matchedTests": [
75
+ "returns 400 when currency is missing",
76
+ "returns 400 for unsupported currency",
77
+ "returns 422 for insufficient funds",
78
+ "returns 401 for invalid token",
79
+ "returns 400 for invalid currency",
80
+ "returns 422 with insufficient funds"
81
+ ],
82
+ "coveredByScanReport": false
83
+ },
84
+ {
85
+ "id": "authorization:get:/wallets/{id}",
86
+ "category": "authorization",
87
+ "description": "Authorization check for GET /wallets/{id}",
88
+ "endpoint": "GET /wallets/{id}",
89
+ "covered": false,
90
+ "matchedTests": [],
91
+ "coveredByScanReport": false
92
+ },
93
+ {
94
+ "id": "input-validation:get:/wallets/{id}",
95
+ "category": "input-validation",
96
+ "description": "Input validation for GET /wallets/{id}",
97
+ "endpoint": "GET /wallets/{id}",
98
+ "covered": true,
99
+ "matchedTests": [
100
+ "returns 422 for insufficient funds",
101
+ "returns 400 for invalid currency",
102
+ "returns 422 with insufficient funds"
103
+ ],
104
+ "coveredByScanReport": false
105
+ },
106
+ {
107
+ "id": "authorization:delete:/wallets/{id}",
108
+ "category": "authorization",
109
+ "description": "Authorization check for DELETE /wallets/{id}",
110
+ "endpoint": "DELETE /wallets/{id}",
111
+ "covered": false,
112
+ "matchedTests": [],
113
+ "coveredByScanReport": false
114
+ },
115
+ {
116
+ "id": "input-validation:delete:/wallets/{id}",
117
+ "category": "input-validation",
118
+ "description": "Input validation for DELETE /wallets/{id}",
119
+ "endpoint": "DELETE /wallets/{id}",
120
+ "covered": true,
121
+ "matchedTests": [
122
+ "returns 422 for insufficient funds",
123
+ "returns 400 for invalid currency",
124
+ "returns 422 with insufficient funds"
125
+ ],
126
+ "coveredByScanReport": false
127
+ },
128
+ {
129
+ "id": "authorization:patch:/wallets/{id}/freeze",
130
+ "category": "authorization",
131
+ "description": "Authorization check for PATCH /wallets/{id}/freeze",
132
+ "endpoint": "PATCH /wallets/{id}/freeze",
133
+ "covered": false,
134
+ "matchedTests": [],
135
+ "coveredByScanReport": false
136
+ },
137
+ {
138
+ "id": "input-validation:patch:/wallets/{id}/freeze",
139
+ "category": "input-validation",
140
+ "description": "Input validation for PATCH /wallets/{id}/freeze",
141
+ "endpoint": "PATCH /wallets/{id}/freeze",
142
+ "covered": false,
143
+ "matchedTests": [],
144
+ "coveredByScanReport": false
145
+ },
146
+ {
147
+ "id": "authorization:patch:/wallets/{id}/unfreeze",
148
+ "category": "authorization",
149
+ "description": "Authorization check for PATCH /wallets/{id}/unfreeze",
150
+ "endpoint": "PATCH /wallets/{id}/unfreeze",
151
+ "covered": false,
152
+ "matchedTests": [],
153
+ "coveredByScanReport": false
154
+ },
155
+ {
156
+ "id": "input-validation:patch:/wallets/{id}/unfreeze",
157
+ "category": "input-validation",
158
+ "description": "Input validation for PATCH /wallets/{id}/unfreeze",
159
+ "endpoint": "PATCH /wallets/{id}/unfreeze",
160
+ "covered": false,
161
+ "matchedTests": [],
162
+ "coveredByScanReport": false
163
+ },
164
+ {
165
+ "id": "authorization:post:/wallets/{id}/fund",
166
+ "category": "authorization",
167
+ "description": "Authorization check for POST /wallets/{id}/fund",
168
+ "endpoint": "POST /wallets/{id}/fund",
169
+ "covered": false,
170
+ "matchedTests": [],
171
+ "coveredByScanReport": false
172
+ },
173
+ {
174
+ "id": "input-validation:post:/wallets/{id}/fund",
175
+ "category": "input-validation",
176
+ "description": "Input validation for POST /wallets/{id}/fund",
177
+ "endpoint": "POST /wallets/{id}/fund",
178
+ "covered": false,
179
+ "matchedTests": [],
180
+ "coveredByScanReport": false
181
+ },
182
+ {
183
+ "id": "authorization:post:/wallets/{id}/debit",
184
+ "category": "authorization",
185
+ "description": "Authorization check for POST /wallets/{id}/debit",
186
+ "endpoint": "POST /wallets/{id}/debit",
187
+ "covered": false,
188
+ "matchedTests": [],
189
+ "coveredByScanReport": false
190
+ },
191
+ {
192
+ "id": "input-validation:post:/wallets/{id}/debit",
193
+ "category": "input-validation",
194
+ "description": "Input validation for POST /wallets/{id}/debit",
195
+ "endpoint": "POST /wallets/{id}/debit",
196
+ "covered": false,
197
+ "matchedTests": [],
198
+ "coveredByScanReport": false
199
+ },
200
+ {
201
+ "id": "authorization:post:/wallets/{id}/transfer",
202
+ "category": "authorization",
203
+ "description": "Authorization check for POST /wallets/{id}/transfer",
204
+ "endpoint": "POST /wallets/{id}/transfer",
205
+ "covered": false,
206
+ "matchedTests": [],
207
+ "coveredByScanReport": false
208
+ },
209
+ {
210
+ "id": "input-validation:post:/wallets/{id}/transfer",
211
+ "category": "input-validation",
212
+ "description": "Input validation for POST /wallets/{id}/transfer",
213
+ "endpoint": "POST /wallets/{id}/transfer",
214
+ "covered": false,
215
+ "matchedTests": [],
216
+ "coveredByScanReport": false
217
+ },
218
+ {
219
+ "id": "authorization:post:/payments",
220
+ "category": "authorization",
221
+ "description": "Authorization check for POST /payments",
222
+ "endpoint": "POST /payments",
223
+ "covered": false,
224
+ "matchedTests": [],
225
+ "coveredByScanReport": false
226
+ },
227
+ {
228
+ "id": "input-validation:post:/payments",
229
+ "category": "input-validation",
230
+ "description": "Input validation for POST /payments",
231
+ "endpoint": "POST /payments",
232
+ "covered": true,
233
+ "matchedTests": [
234
+ "returns 400 for missing required fields",
235
+ "returns 422 for invalid (non-existent) wallet",
236
+ "returns 422 when refunding a non-completed payment"
237
+ ],
238
+ "coveredByScanReport": false
239
+ },
240
+ {
241
+ "id": "authorization:get:/payments/{id}",
242
+ "category": "authorization",
243
+ "description": "Authorization check for GET /payments/{id}",
244
+ "endpoint": "GET /payments/{id}",
245
+ "covered": false,
246
+ "matchedTests": [],
247
+ "coveredByScanReport": false
248
+ },
249
+ {
250
+ "id": "input-validation:get:/payments/{id}",
251
+ "category": "input-validation",
252
+ "description": "Input validation for GET /payments/{id}",
253
+ "endpoint": "GET /payments/{id}",
254
+ "covered": true,
255
+ "matchedTests": [
256
+ "returns 422 when refunding a non-completed payment"
257
+ ],
258
+ "coveredByScanReport": false
259
+ },
260
+ {
261
+ "id": "authorization:post:/payments/{id}/refund",
262
+ "category": "authorization",
263
+ "description": "Authorization check for POST /payments/{id}/refund",
264
+ "endpoint": "POST /payments/{id}/refund",
265
+ "covered": false,
266
+ "matchedTests": [],
267
+ "coveredByScanReport": false
268
+ },
269
+ {
270
+ "id": "input-validation:post:/payments/{id}/refund",
271
+ "category": "input-validation",
272
+ "description": "Input validation for POST /payments/{id}/refund",
273
+ "endpoint": "POST /payments/{id}/refund",
274
+ "covered": false,
275
+ "matchedTests": [],
276
+ "coveredByScanReport": false
277
+ },
278
+ {
279
+ "id": "authorization:get:/transactions",
280
+ "category": "authorization",
281
+ "description": "Authorization check for GET /transactions",
282
+ "endpoint": "GET /transactions",
283
+ "covered": false,
284
+ "matchedTests": [],
285
+ "coveredByScanReport": false
286
+ },
287
+ {
288
+ "id": "authentication:JWT",
289
+ "category": "authentication",
290
+ "description": "JWT token signature and expiry validation",
291
+ "covered": true,
292
+ "matchedTests": [
293
+ "returns 401 for expired JWT",
294
+ "returns 401 for invalid JWT signature"
295
+ ],
296
+ "coveredByScanReport": false
297
+ }
298
+ ]
299
+ }
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="31.88" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 257"><defs><linearGradient id="IconifyId1813088fe1fbc01fb466" x1="-.828%" x2="57.636%" y1="7.652%" y2="78.411%"><stop offset="0%" stop-color="#41D1FF"></stop><stop offset="100%" stop-color="#BD34FE"></stop></linearGradient><linearGradient id="IconifyId1813088fe1fbc01fb467" x1="43.376%" x2="50.316%" y1="2.242%" y2="89.03%"><stop offset="0%" stop-color="#FFEA83"></stop><stop offset="8.333%" stop-color="#FFDD35"></stop><stop offset="100%" stop-color="#FFA800"></stop></linearGradient></defs><path fill="url(#IconifyId1813088fe1fbc01fb466)" d="M255.153 37.938L134.897 252.976c-2.483 4.44-8.862 4.466-11.382.048L.875 37.958c-2.746-4.814 1.371-10.646 6.827-9.67l120.385 21.517a6.537 6.537 0 0 0 2.322-.004l117.867-21.483c5.438-.991 9.574 4.796 6.877 9.62Z"></path><path fill="url(#IconifyId1813088fe1fbc01fb467)" d="M185.432.063L96.44 17.501a3.268 3.268 0 0 0-2.634 3.014l-5.474 92.456a3.268 3.268 0 0 0 3.997 3.378l24.777-5.718c2.318-.535 4.413 1.507 3.936 3.838l-7.361 36.047c-.495 2.426 1.782 4.5 4.151 3.78l15.304-4.649c2.372-.72 4.652 1.36 4.15 3.788l-11.698 56.621c-.732 3.542 3.979 5.473 5.943 2.437l1.313-2.028l72.516-144.72c1.215-2.423-.88-5.186-3.54-4.672l-25.505 4.922c-2.396.462-4.435-1.77-3.759-4.114l16.646-57.705c.677-2.35-1.37-4.583-3.769-4.113Z"></path></svg>
package/dist/src/index.js CHANGED
@@ -59,6 +59,7 @@ const astAnalysisOrchestrator_1 = require("./ast/astAnalysisOrchestrator");
59
59
  const projectDiscovery_1 = require("./discovery/projectDiscovery");
60
60
  const businessRuleInference_1 = require("./inference/businessRuleInference");
61
61
  const integrationFlowInference_1 = require("./inference/integrationFlowInference");
62
+ const serveDashboard_1 = require("./serveDashboard");
62
63
  // Register all language AST analyzers at startup.
63
64
  // This side-effect import ensures each language module's registerAnalyzer() call runs.
64
65
  (0, astAnalysisOrchestrator_1.registerAllAnalyzers)();
@@ -1344,8 +1345,11 @@ program
1344
1345
  .option('--export-inferred-rules', 'Export inferred rules/flows as editable YAML files')
1345
1346
  .option('--no-infer-business-rules', 'Disable business rule inference')
1346
1347
  .option('--no-infer-integration-flows', 'Disable integration flow inference')
1348
+ .option('--dashboard', 'Start the coverage dashboard after analysis')
1349
+ .option('--port <port>', 'Port for the dashboard server (requires --dashboard)', parseInt)
1350
+ .option('--open', 'Open the dashboard in your browser automatically (requires --dashboard)')
1347
1351
  .action(async (options) => {
1348
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
1352
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l;
1349
1353
  const { metricsPort, serviceName } = setupObservability();
1350
1354
  const logger = (0, observability_1.getLogger)();
1351
1355
  const configPath = program.opts()['config'];
@@ -1419,11 +1423,48 @@ program
1419
1423
  console.log(' Exported: generated-integration-flows.yaml');
1420
1424
  }
1421
1425
  }
1422
- // ── 4. Emit warnings ───────────────────────────────────────────────────
1426
+ // ── 4. Endpoint coverage analysis → coverage-summary.json ─────────────
1427
+ const allCoverageResults = [];
1428
+ if (artifacts.specs.length > 0) {
1429
+ const testsGlob = artifacts.testFiles.length > 0
1430
+ ? '{' + artifacts.testFiles.join(',') + '}'
1431
+ : path.join(rootDir, '**', '*');
1432
+ const detectedLanguages = artifacts.languages;
1433
+ for (const specPath of artifacts.specs) {
1434
+ try {
1435
+ console.log(`\nAnalyzing endpoint coverage for: ${path.basename(specPath)}`);
1436
+ const endpoints = await (0, endpointCoverage_1.parseOpenApiSpec)(specPath);
1437
+ const coverageMap = await (0, endpointCoverage_1.analyzeTestCoverage)(endpoints, testsGlob, detectedLanguages);
1438
+ const report = (0, endpointCoverage_1.buildCoverageReport)(coverageMap);
1439
+ const result = {
1440
+ type: 'endpoint',
1441
+ totalItems: report.total,
1442
+ coveredItems: report.covered,
1443
+ coveragePercent: report.percentage,
1444
+ details: report,
1445
+ };
1446
+ allCoverageResults.push(result);
1447
+ console.log(` ${report.covered}/${report.total} endpoints covered (${report.percentage}%)`);
1448
+ }
1449
+ catch (err) {
1450
+ warnings.push(`Endpoint coverage failed for ${path.basename(specPath)}: ` +
1451
+ `${err instanceof Error ? err.message : String(err)}`);
1452
+ }
1453
+ }
1454
+ if (allCoverageResults.length > 0) {
1455
+ const observabilityInfo = (0, observability_1.buildObservabilityInfo)(metricsPort);
1456
+ (0, reporting_1.generateMultiFormatReports)(allCoverageResults, ['json'], reportsDir, {}, observabilityInfo);
1457
+ console.log(`\nReports written to: ${reportsDir}`);
1458
+ }
1459
+ }
1460
+ else {
1461
+ warnings.push('No API spec files found; endpoint coverage analysis skipped.');
1462
+ }
1463
+ // ── 5. Emit warnings ───────────────────────────────────────────────────
1423
1464
  for (const w of warnings) {
1424
1465
  console.warn(`[WARN] ${w}`);
1425
1466
  }
1426
- // ── 5. Configuration override log ──────────────────────────────────────
1467
+ // ── 6. Configuration override log ──────────────────────────────────────
1427
1468
  if (options['inferBusinessRules'] === false) {
1428
1469
  console.log('\nConfiguration override detected: business rule inference disabled via CLI');
1429
1470
  }
@@ -1431,7 +1472,36 @@ program
1431
1472
  console.log('\nConfiguration override detected: integration flow inference disabled via CLI');
1432
1473
  }
1433
1474
  logger.info({ event: 'analyze_complete', warnings: warnings.length }, 'Agnostic project analysis complete');
1434
- await finaliseObservability([], {}, metricsPort, serviceName);
1475
+ await finaliseObservability(allCoverageResults, {}, metricsPort, serviceName);
1476
+ // ── 7. Optionally launch the dashboard ─────────────────────────────────
1477
+ if (options['dashboard']) {
1478
+ (0, serveDashboard_1.serveDashboard)({
1479
+ reportsDir: reportsDir,
1480
+ port: (_l = options['port']) !== null && _l !== void 0 ? _l : 4000,
1481
+ open: Boolean(options['open']),
1482
+ });
1483
+ // Keep the process alive — the HTTP server holds the event loop open
1484
+ }
1485
+ });
1486
+ // ─── serve command ────────────────────────────────────────────────────────────
1487
+ program
1488
+ .command('serve')
1489
+ .description('Start the coverage dashboard UI and serve reports from your reports directory.')
1490
+ .option('--reports-dir <dir>', 'Directory containing report JSON files (default: reports/)')
1491
+ .option('--port <port>', 'Port to listen on (default: 4000)', parseInt)
1492
+ .option('--open', 'Open the dashboard in your browser automatically')
1493
+ .action((options) => {
1494
+ var _a, _b, _c, _d;
1495
+ const configPath = program.opts()['config'];
1496
+ const analyzerCfg = (0, config_1.loadCentralConfig)(configPath);
1497
+ const reportsDir = (_c = (_a = options['reportsDir']) !== null && _a !== void 0 ? _a : (_b = analyzerCfg.reports) === null || _b === void 0 ? void 0 : _b.outputDir) !== null && _c !== void 0 ? _c : 'reports';
1498
+ const port = (_d = options['port']) !== null && _d !== void 0 ? _d : 4000;
1499
+ (0, serveDashboard_1.serveDashboard)({
1500
+ reportsDir,
1501
+ port,
1502
+ open: Boolean(options['open']),
1503
+ });
1504
+ // Keep the process alive while the server runs
1435
1505
  });
1436
1506
  // Parse the command-line arguments
1437
1507
  program.parse(process.argv);
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Built-in dashboard HTTP server.
3
+ *
4
+ * Serves the pre-built React dashboard from the npm package's
5
+ * `dashboard/dist/` directory and intercepts `/reports/*` requests to
6
+ * serve from the caller's actual reports directory — giving every user
7
+ * a live dashboard against their own coverage data with a single command.
8
+ *
9
+ * Usage (via CLI):
10
+ * npx api-tests-coverage serve [--reports-dir reports/] [--port 4000] [--open]
11
+ */
12
+ import * as http from 'http';
13
+ export interface ServeDashboardOptions {
14
+ /** Directory containing coverage report JSON files. Default: reports/ */
15
+ reportsDir?: string;
16
+ /** Port to listen on. Default: 4000 */
17
+ port?: number;
18
+ /** Open the browser automatically. Default: false */
19
+ open?: boolean;
20
+ }
21
+ /**
22
+ * Start the dashboard HTTP server and return the server instance.
23
+ *
24
+ * The server:
25
+ * 1. Intercepts `/reports/*` → serves from `reportsDir`
26
+ * 2. Everything else → serves static files from `dashboard/dist/`
27
+ * 3. Unknown paths fall back to `index.html` (SPA client-side routing)
28
+ */
29
+ export declare function serveDashboard(options?: ServeDashboardOptions): http.Server;
30
+ //# sourceMappingURL=serveDashboard.d.ts.map
@@ -0,0 +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"}
@@ -0,0 +1,191 @@
1
+ "use strict";
2
+ /**
3
+ * Built-in dashboard HTTP server.
4
+ *
5
+ * Serves the pre-built React dashboard from the npm package's
6
+ * `dashboard/dist/` directory and intercepts `/reports/*` requests to
7
+ * serve from the caller's actual reports directory — giving every user
8
+ * a live dashboard against their own coverage data with a single command.
9
+ *
10
+ * Usage (via CLI):
11
+ * npx api-tests-coverage serve [--reports-dir reports/] [--port 4000] [--open]
12
+ */
13
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
14
+ if (k2 === undefined) k2 = k;
15
+ var desc = Object.getOwnPropertyDescriptor(m, k);
16
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
17
+ desc = { enumerable: true, get: function() { return m[k]; } };
18
+ }
19
+ Object.defineProperty(o, k2, desc);
20
+ }) : (function(o, m, k, k2) {
21
+ if (k2 === undefined) k2 = k;
22
+ o[k2] = m[k];
23
+ }));
24
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
25
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
26
+ }) : function(o, v) {
27
+ o["default"] = v;
28
+ });
29
+ var __importStar = (this && this.__importStar) || (function () {
30
+ var ownKeys = function(o) {
31
+ ownKeys = Object.getOwnPropertyNames || function (o) {
32
+ var ar = [];
33
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
34
+ return ar;
35
+ };
36
+ return ownKeys(o);
37
+ };
38
+ return function (mod) {
39
+ if (mod && mod.__esModule) return mod;
40
+ var result = {};
41
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
42
+ __setModuleDefault(result, mod);
43
+ return result;
44
+ };
45
+ })();
46
+ Object.defineProperty(exports, "__esModule", { value: true });
47
+ exports.serveDashboard = serveDashboard;
48
+ const http = __importStar(require("http"));
49
+ const fs = __importStar(require("fs"));
50
+ const path = __importStar(require("path"));
51
+ const url = __importStar(require("url"));
52
+ const child_process_1 = require("child_process");
53
+ // ─── MIME type map ─────────────────────────────────────────────────────────────
54
+ const MIME_TYPES = {
55
+ '.html': 'text/html; charset=utf-8',
56
+ '.js': 'application/javascript; charset=utf-8',
57
+ '.mjs': 'application/javascript; charset=utf-8',
58
+ '.css': 'text/css; charset=utf-8',
59
+ '.json': 'application/json; charset=utf-8',
60
+ '.svg': 'image/svg+xml',
61
+ '.png': 'image/png',
62
+ '.ico': 'image/x-icon',
63
+ '.woff': 'font/woff',
64
+ '.woff2': 'font/woff2',
65
+ '.ttf': 'font/ttf',
66
+ '.jtl': 'text/plain',
67
+ '.csv': 'text/csv',
68
+ '.xml': 'application/xml',
69
+ };
70
+ // ─── Dashboard location ───────────────────────────────────────────────────────
71
+ /**
72
+ * Resolve the path to the pre-built dashboard static files.
73
+ *
74
+ * Checks two locations (first match wins):
75
+ * 1. dist/dashboard/ — npm-published package (prepublishOnly copies dashboard/dist here)
76
+ * 2. dashboard/dist/ — repo clone with dashboard already built (make dashboard-build)
77
+ */
78
+ function resolveDashboardDir() {
79
+ // dist/src/serveDashboard.js → ../dashboard → dist/dashboard/ (npm package)
80
+ const inDist = path.resolve(__dirname, '..', 'dashboard');
81
+ if (fs.existsSync(path.join(inDist, 'index.html'))) {
82
+ return inDist;
83
+ }
84
+ // Fallback for local development: dist/src/ → ../../dashboard/dist → dashboard/dist/
85
+ const inRepo = path.resolve(__dirname, '..', '..', 'dashboard', 'dist');
86
+ if (fs.existsSync(path.join(inRepo, 'index.html'))) {
87
+ return inRepo;
88
+ }
89
+ throw new Error(`Dashboard build not found.\n` +
90
+ `Run: cd dashboard && npm run build\n` +
91
+ `Or: make dashboard-build`);
92
+ }
93
+ /**
94
+ * Start the dashboard HTTP server and return the server instance.
95
+ *
96
+ * The server:
97
+ * 1. Intercepts `/reports/*` → serves from `reportsDir`
98
+ * 2. Everything else → serves static files from `dashboard/dist/`
99
+ * 3. Unknown paths fall back to `index.html` (SPA client-side routing)
100
+ */
101
+ function serveDashboard(options = {}) {
102
+ var _a, _b;
103
+ const reportsDir = path.resolve((_a = options.reportsDir) !== null && _a !== void 0 ? _a : 'reports');
104
+ const port = (_b = options.port) !== null && _b !== void 0 ? _b : 4000;
105
+ const dashboardDir = resolveDashboardDir();
106
+ const server = http.createServer((req, res) => {
107
+ var _a, _b, _c, _d;
108
+ const parsedUrl = url.parse((_a = req.url) !== null && _a !== void 0 ? _a : '/');
109
+ let pathname = (_b = parsedUrl.pathname) !== null && _b !== void 0 ? _b : '/';
110
+ // ── 1. Serve /reports/* from the actual reports directory ──────────────
111
+ if (pathname.startsWith('/reports/')) {
112
+ const relative = pathname.slice('/reports/'.length);
113
+ const reportPath = path.join(reportsDir, relative);
114
+ // Security: prevent path traversal
115
+ if (!reportPath.startsWith(reportsDir + path.sep) && reportPath !== reportsDir) {
116
+ res.writeHead(403);
117
+ res.end('Forbidden');
118
+ return;
119
+ }
120
+ try {
121
+ const content = fs.readFileSync(reportPath);
122
+ const mimeType = (_c = MIME_TYPES[path.extname(reportPath)]) !== null && _c !== void 0 ? _c : 'application/octet-stream';
123
+ res.writeHead(200, {
124
+ 'Content-Type': mimeType,
125
+ 'Cache-Control': 'no-cache',
126
+ 'Access-Control-Allow-Origin': '*',
127
+ });
128
+ res.end(content);
129
+ }
130
+ catch {
131
+ res.writeHead(404, { 'Content-Type': 'application/json' });
132
+ res.end(JSON.stringify({ error: `Report not found: ${relative}` }));
133
+ }
134
+ return;
135
+ }
136
+ // ── 2. Serve static dashboard assets ───────────────────────────────────
137
+ if (pathname === '/')
138
+ pathname = '/index.html';
139
+ const filePath = path.join(dashboardDir, pathname);
140
+ // Security: prevent escaping dashboard dir
141
+ if (!filePath.startsWith(dashboardDir)) {
142
+ res.writeHead(403);
143
+ res.end('Forbidden');
144
+ return;
145
+ }
146
+ try {
147
+ const content = fs.readFileSync(filePath);
148
+ const mimeType = (_d = MIME_TYPES[path.extname(filePath)]) !== null && _d !== void 0 ? _d : 'text/plain';
149
+ res.writeHead(200, {
150
+ 'Content-Type': mimeType,
151
+ 'Cache-Control': path.extname(filePath) === '.html' ? 'no-cache' : 'max-age=86400',
152
+ });
153
+ res.end(content);
154
+ }
155
+ catch {
156
+ // ── 3. SPA fallback — serve index.html for all unknown paths ───────
157
+ try {
158
+ const indexContent = fs.readFileSync(path.join(dashboardDir, 'index.html'));
159
+ res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8', 'Cache-Control': 'no-cache' });
160
+ res.end(indexContent);
161
+ }
162
+ catch {
163
+ res.writeHead(500, { 'Content-Type': 'text/plain' });
164
+ res.end('Dashboard build missing. Run: cd dashboard && npm run build');
165
+ }
166
+ }
167
+ });
168
+ server.listen(port, () => {
169
+ const serverUrl = `http://localhost:${port}`;
170
+ console.log(`\n=== API Coverage Dashboard ===`);
171
+ console.log(` URL: ${serverUrl}`);
172
+ console.log(` Reports dir: ${reportsDir}`);
173
+ console.log(`\nPress Ctrl+C to stop.\n`);
174
+ if (options.open) {
175
+ openBrowser(serverUrl);
176
+ }
177
+ });
178
+ return server;
179
+ }
180
+ // ─── Browser opener ───────────────────────────────────────────────────────────
181
+ function openBrowser(targetUrl) {
182
+ try {
183
+ const cmd = process.platform === 'darwin' ? `open "${targetUrl}"` :
184
+ process.platform === 'win32' ? `start "" "${targetUrl}"` :
185
+ `xdg-open "${targetUrl}"`;
186
+ (0, child_process_1.execSync)(cmd, { stdio: 'ignore' });
187
+ }
188
+ catch {
189
+ // Silently ignore — browser open is best-effort
190
+ }
191
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "api-tests-coverage",
3
- "version": "1.0.0",
3
+ "version": "1.0.2",
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",
@@ -10,6 +10,7 @@
10
10
  "files": [
11
11
  "dist/src/",
12
12
  "dist/action/",
13
+ "dist/dashboard/",
13
14
  "README.md",
14
15
  "config.yaml.example"
15
16
  ],
@@ -35,7 +36,7 @@
35
36
  "license": "MIT",
36
37
  "scripts": {
37
38
  "build": "tsc",
38
- "prepublishOnly": "npm run build",
39
+ "prepublishOnly": "npm run build && cd dashboard && npm run build && cd .. && cp -r dashboard/dist dist/dashboard",
39
40
  "start": "node dist/src/index.js",
40
41
  "test": "jest",
41
42
  "coverage": "node scripts/run-coverage.js",