@ovh-ux/manager-static-analysis-kit 0.7.1 → 0.9.0
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/CHANGELOG.md +48 -0
- package/README.md +59 -69
- package/bin/cli-path-config.js +31 -0
- package/bin/code-duplication-cli.js +96 -0
- package/bin/code-duplication-tests-cli.js +68 -0
- package/bin/lint-cli.js +18 -16
- package/bin/perf-budgets-cli.js +120 -0
- package/bin/perf-budgets-tests-cli.js +72 -0
- package/bin/static-dynamic-quality-checks.js +138 -0
- package/bin/tests-coverage-cli-tests.js +67 -0
- package/bin/tests-coverage-cli.js +135 -0
- package/bin/types-coverage-cli.js +127 -0
- package/bin/types-coverage-tests-cli.js +68 -0
- package/bin/utils/apps-utils.js +64 -0
- package/bin/utils/args-parse-utils.js +222 -0
- package/bin/utils/file-utils.js +52 -0
- package/bin/utils/log-utils.js +29 -0
- package/bin/utils/runner-utils.js +85 -0
- package/bin/utils/turbo-utils.js +139 -0
- package/dist/adapters/code-duplication/helpers/code-duplication-analysis-helper.d.ts +6 -0
- package/dist/adapters/code-duplication/helpers/code-duplication-analysis-helper.d.ts.map +1 -0
- package/dist/adapters/code-duplication/helpers/code-duplication-analysis-helper.js +240 -0
- package/dist/adapters/code-duplication/types/CodeDuplication.d.ts +60 -0
- package/dist/adapters/code-duplication/types/CodeDuplication.d.ts.map +1 -0
- package/dist/adapters/code-duplication/types/CodeDuplication.js +1 -0
- package/dist/adapters/eslint/rules/eslint-naming-conventions.d.ts.map +1 -1
- package/dist/adapters/eslint/rules/eslint-naming-conventions.js +1 -0
- package/dist/adapters/eslint/rules/eslint-prettier.js +1 -1
- package/dist/adapters/html-a11y-validation/helpers/html-a11y-tests-setup.d.ts +62 -0
- package/dist/adapters/html-a11y-validation/helpers/html-a11y-tests-setup.d.ts.map +1 -0
- package/dist/adapters/html-a11y-validation/helpers/html-a11y-tests-setup.js +73 -0
- package/dist/adapters/html-w3c-validation/helpers/html-w3c-tests-setup.d.ts +19 -0
- package/dist/adapters/html-w3c-validation/helpers/html-w3c-tests-setup.d.ts.map +1 -0
- package/dist/adapters/html-w3c-validation/helpers/html-w3c-tests-setup.js +32 -0
- package/dist/adapters/html-w3c-validation/helpers/html-w3c-validator.d.ts +4 -0
- package/dist/adapters/html-w3c-validation/helpers/html-w3c-validator.d.ts.map +1 -0
- package/dist/adapters/html-w3c-validation/helpers/html-w3c-validator.js +89 -0
- package/dist/adapters/html-w3c-validation/types/HtmlW3CValidator.d.ts +6 -0
- package/dist/adapters/html-w3c-validation/types/HtmlW3CValidator.d.ts.map +1 -0
- package/dist/adapters/html-w3c-validation/types/HtmlW3CValidator.js +1 -0
- package/dist/adapters/html-w3c-validation/types/globals/vnu-jar.d.ts +5 -0
- package/dist/adapters/perf-budgets/helpers/perfs-bundle-analysis-helper.d.ts +7 -0
- package/dist/adapters/perf-budgets/helpers/perfs-bundle-analysis-helper.d.ts.map +1 -0
- package/dist/adapters/perf-budgets/helpers/perfs-bundle-analysis-helper.js +191 -0
- package/dist/adapters/perf-budgets/rules/perfs-budgets-rules.d.ts +10 -0
- package/dist/adapters/perf-budgets/rules/perfs-budgets-rules.d.ts.map +1 -0
- package/dist/adapters/perf-budgets/rules/perfs-budgets-rules.js +20 -0
- package/dist/adapters/perf-budgets/rules/perfs-budgets-scoring.d.ts +5 -0
- package/dist/adapters/perf-budgets/rules/perfs-budgets-scoring.d.ts.map +1 -0
- package/dist/adapters/perf-budgets/rules/perfs-budgets-scoring.js +35 -0
- package/dist/adapters/perf-budgets/types/PerfBudget.d.ts +22 -0
- package/dist/adapters/perf-budgets/types/PerfBudget.d.ts.map +1 -0
- package/dist/adapters/perf-budgets/types/PerfBudget.js +1 -0
- package/dist/adapters/perf-budgets/types/PerfBudgetAssets.d.ts +13 -0
- package/dist/adapters/perf-budgets/types/PerfBudgetAssets.d.ts.map +1 -0
- package/dist/adapters/perf-budgets/types/PerfBudgetAssets.js +1 -0
- package/dist/adapters/perf-budgets/types/PerfBudgetScore.d.ts +13 -0
- package/dist/adapters/perf-budgets/types/PerfBudgetScore.d.ts.map +1 -0
- package/dist/adapters/perf-budgets/types/PerfBudgetScore.js +1 -0
- package/dist/adapters/tests-coverage/helpers/tests-coverage-analysis-helper.d.ts +4 -0
- package/dist/adapters/tests-coverage/helpers/tests-coverage-analysis-helper.d.ts.map +1 -0
- package/dist/adapters/tests-coverage/helpers/tests-coverage-analysis-helper.js +192 -0
- package/dist/adapters/tests-coverage/types/TestsCoverage.d.ts +36 -0
- package/dist/adapters/tests-coverage/types/TestsCoverage.d.ts.map +1 -0
- package/dist/adapters/tests-coverage/types/TestsCoverage.js +6 -0
- package/dist/adapters/types-coverage/helpers/types-coverage-analysis-helper.d.ts +4 -0
- package/dist/adapters/types-coverage/helpers/types-coverage-analysis-helper.d.ts.map +1 -0
- package/dist/adapters/types-coverage/helpers/types-coverage-analysis-helper.js +158 -0
- package/dist/adapters/types-coverage/types/TypesCoverage.d.ts +30 -0
- package/dist/adapters/types-coverage/types/TypesCoverage.d.ts.map +1 -0
- package/dist/adapters/types-coverage/types/TypesCoverage.js +1 -0
- package/dist/configs/architecture-analysis-config.d.ts +5 -0
- package/dist/configs/architecture-analysis-config.d.ts.map +1 -0
- package/dist/configs/{madge-config.js → architecture-analysis-config.js} +1 -1
- package/dist/configs/assets-budgets-config.d.ts +28 -0
- package/dist/configs/assets-budgets-config.d.ts.map +1 -0
- package/dist/configs/assets-budgets-config.js +45 -0
- package/dist/configs/bundle-analysis-config.d.ts +8 -0
- package/dist/configs/bundle-analysis-config.d.ts.map +1 -0
- package/dist/configs/bundle-analysis-config.js +7 -0
- package/dist/configs/code-duplication-config.d.ts +21 -0
- package/dist/configs/code-duplication-config.d.ts.map +1 -0
- package/dist/configs/code-duplication-config.js +21 -0
- package/dist/configs/{prettier-config.d.ts → code-formatter-config.d.ts} +1 -1
- package/dist/configs/code-formatter-config.d.ts.map +1 -0
- package/dist/configs/file-globs-config.d.ts +1 -4
- package/dist/configs/file-globs-config.d.ts.map +1 -1
- package/dist/configs/file-globs-config.js +1 -4
- package/dist/configs/naming-conventions-config.d.ts.map +1 -1
- package/dist/configs/naming-conventions-config.js +2 -0
- package/dist/configs/shared-exclusion-patterns.d.ts.map +1 -1
- package/dist/configs/shared-exclusion-patterns.js +3 -1
- package/dist/configs/tests-coverage-config.d.ts +12 -0
- package/dist/configs/tests-coverage-config.d.ts.map +1 -0
- package/dist/configs/tests-coverage-config.js +11 -0
- package/dist/configs/types-coverage-config.d.ts +19 -0
- package/dist/configs/types-coverage-config.d.ts.map +1 -0
- package/dist/configs/types-coverage-config.js +27 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +35 -7
- package/dist/configs/jscpd-config.d.ts +0 -7
- package/dist/configs/jscpd-config.d.ts.map +0 -1
- package/dist/configs/jscpd-config.js +0 -7
- package/dist/configs/madge-config.d.ts +0 -5
- package/dist/configs/madge-config.d.ts.map +0 -1
- package/dist/configs/prettier-config.d.ts.map +0 -1
- /package/dist/configs/{prettier-config.js → code-formatter-config.js} +0 -0
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { assetsBudgetsConfig } from '../../../configs/assets-budgets-config.js';
|
|
4
|
+
import { evaluatePerfBudgets } from '../rules/perfs-budgets-rules.js';
|
|
5
|
+
import { scoreAllPerfBudgets } from '../rules/perfs-budgets-scoring.js';
|
|
6
|
+
export function escapeHtml(str) {
|
|
7
|
+
return String(str)
|
|
8
|
+
.replace(/&/g, '&')
|
|
9
|
+
.replace(/</g, '<')
|
|
10
|
+
.replace(/>/g, '>')
|
|
11
|
+
.replace(/"/g, '"')
|
|
12
|
+
.replace(/'/g, ''');
|
|
13
|
+
}
|
|
14
|
+
const buildAssetsInfos = (data) => data.map((entry) => {
|
|
15
|
+
const filename = entry?.filename ?? 'unknown';
|
|
16
|
+
const sizeKb = typeof entry?.parsedSize === 'number' ? entry.parsedSize / 1024 : 0;
|
|
17
|
+
let type = 'other';
|
|
18
|
+
if (/\.js$/i.test(filename))
|
|
19
|
+
type = 'js';
|
|
20
|
+
else if (/\.css$/i.test(filename))
|
|
21
|
+
type = 'css';
|
|
22
|
+
else if (/\.html$/i.test(filename))
|
|
23
|
+
type = 'html';
|
|
24
|
+
else if (/\.(png|jpe?g|gif|svg|webp)$/i.test(filename))
|
|
25
|
+
type = 'img';
|
|
26
|
+
return { filename, type, sizeKb };
|
|
27
|
+
});
|
|
28
|
+
export function parseAnalyzerJson(raw) {
|
|
29
|
+
if (!Array.isArray(raw)) {
|
|
30
|
+
return { jsKb: 0, cssKb: 0, htmlKb: 0, imgKb: 0, assets: [] };
|
|
31
|
+
}
|
|
32
|
+
const assets = buildAssetsInfos(raw);
|
|
33
|
+
const sumByType = (type) => assets.filter((a) => a.type === type).reduce((sum, a) => sum + a.sizeKb, 0);
|
|
34
|
+
return {
|
|
35
|
+
jsKb: sumByType('js'),
|
|
36
|
+
cssKb: sumByType('css'),
|
|
37
|
+
htmlKb: sumByType('html'),
|
|
38
|
+
imgKb: sumByType('img'),
|
|
39
|
+
assets,
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
export function collectPerfBudgets(reportOutputDir) {
|
|
43
|
+
const reportsRoot = path.join(reportOutputDir);
|
|
44
|
+
if (!fs.existsSync(reportsRoot)) {
|
|
45
|
+
throw new Error(`Reports directory not found: ${reportsRoot}`);
|
|
46
|
+
}
|
|
47
|
+
const apps = fs.readdirSync(reportsRoot).filter((d) => {
|
|
48
|
+
const appJson = path.join(reportsRoot, d, 'bundle-report.json');
|
|
49
|
+
return fs.existsSync(appJson);
|
|
50
|
+
});
|
|
51
|
+
const results = [];
|
|
52
|
+
for (const app of apps) {
|
|
53
|
+
const jsonPath = path.join(reportsRoot, app, 'bundle-report.json');
|
|
54
|
+
const raw = JSON.parse(fs.readFileSync(jsonPath, 'utf-8'));
|
|
55
|
+
const { jsKb, cssKb, htmlKb, imgKb, assets } = parseAnalyzerJson(raw);
|
|
56
|
+
const appResult = {
|
|
57
|
+
...evaluatePerfBudgets({ app, jsKb, cssKb, htmlKb, imgKb }),
|
|
58
|
+
assets,
|
|
59
|
+
};
|
|
60
|
+
results.push(appResult);
|
|
61
|
+
}
|
|
62
|
+
const scores = scoreAllPerfBudgets(results);
|
|
63
|
+
return {
|
|
64
|
+
results,
|
|
65
|
+
scores,
|
|
66
|
+
medians: assetsBudgetsConfig.medians,
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
export function generatePerfBudgetsHtml(summary) {
|
|
70
|
+
const { results, scores, medians } = summary;
|
|
71
|
+
const heavyCount = assetsBudgetsConfig.heavyAssetsCount;
|
|
72
|
+
function colorizeClass(status) {
|
|
73
|
+
switch (status) {
|
|
74
|
+
case 'ok':
|
|
75
|
+
return 'status-ok';
|
|
76
|
+
case 'near':
|
|
77
|
+
return 'status-near';
|
|
78
|
+
case 'exceed':
|
|
79
|
+
return 'status-exceed';
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
function heaviestOfType(assets, type) {
|
|
83
|
+
return assets.filter((a) => a.type === type).sort((a, b) => b.sizeKb - a.sizeKb)[0];
|
|
84
|
+
}
|
|
85
|
+
function formatCell(total, status, type, assets) {
|
|
86
|
+
const heavy = heaviestOfType(assets, type);
|
|
87
|
+
const heavyInfo = heavy
|
|
88
|
+
? `<br/><small><b>Largest ${type.toUpperCase()} asset:</b> <code>${escapeHtml(heavy.filename)}</code> — ${heavy.sizeKb.toFixed(1)} KB</small>`
|
|
89
|
+
: '';
|
|
90
|
+
return `<td class="${colorizeClass(status)}">
|
|
91
|
+
<b>Total ${type.toUpperCase()} assets size:</b> ${total.toFixed(1)} KB
|
|
92
|
+
${heavyInfo}
|
|
93
|
+
</td>`;
|
|
94
|
+
}
|
|
95
|
+
const rows = scores
|
|
96
|
+
.map((s) => {
|
|
97
|
+
const result = results.find((r) => r.app === s.app);
|
|
98
|
+
const heavyAssets = [...result.assets]
|
|
99
|
+
.sort((a, b) => b.sizeKb - a.sizeKb)
|
|
100
|
+
.slice(0, heavyCount);
|
|
101
|
+
const assetsHtml = heavyAssets
|
|
102
|
+
.map((a) => `<li><code>${escapeHtml(a.filename)}</code> — <strong>${a.sizeKb.toFixed(1)} KB</strong> (${a.type})</li>`)
|
|
103
|
+
.join('\n');
|
|
104
|
+
return `
|
|
105
|
+
<tr>
|
|
106
|
+
<td><strong>${escapeHtml(s.app)}</strong></td>
|
|
107
|
+
${formatCell(result.jsKb, result.jsStatus, 'js', result.assets)}
|
|
108
|
+
${formatCell(result.cssKb, result.cssStatus, 'css', result.assets)}
|
|
109
|
+
${formatCell(result.htmlKb, result.htmlStatus, 'html', result.assets)}
|
|
110
|
+
${formatCell(result.imgKb, result.imgStatus, 'img', result.assets)}
|
|
111
|
+
<td><b>${escapeHtml(s.status.toUpperCase())}</b></td>
|
|
112
|
+
<td>
|
|
113
|
+
<details>
|
|
114
|
+
<summary>Top ${heavyCount} Assets</summary>
|
|
115
|
+
<ul>${assetsHtml || '<li>No assets found</li>'}</ul>
|
|
116
|
+
</details>
|
|
117
|
+
</td>
|
|
118
|
+
</tr>
|
|
119
|
+
`;
|
|
120
|
+
})
|
|
121
|
+
.join('\n');
|
|
122
|
+
const linksHtml = assetsBudgetsConfig.links.httpArchive
|
|
123
|
+
.map(({ label, url }) => `<li><a href="${escapeHtml(url)}" target="_blank">${escapeHtml(label)}</a></li>`)
|
|
124
|
+
.join('\n');
|
|
125
|
+
const tipsHtml = assetsBudgetsConfig.links.tips
|
|
126
|
+
.map(({ label, desc }) => `<li><strong>${escapeHtml(label)}:</strong> ${escapeHtml(desc)}</li>`)
|
|
127
|
+
.join('\n');
|
|
128
|
+
const optimizationHtml = assetsBudgetsConfig.links.optimization
|
|
129
|
+
.map(({ label, url }) => `<li><a href="${escapeHtml(url)}" target="_blank">${escapeHtml(label)}</a></li>`)
|
|
130
|
+
.join('\n');
|
|
131
|
+
return `
|
|
132
|
+
<html lang="en">
|
|
133
|
+
<head>
|
|
134
|
+
<meta charset="UTF-8" />
|
|
135
|
+
<title>Perf Budgets Report</title>
|
|
136
|
+
<style>
|
|
137
|
+
body { font-family: Arial, sans-serif; padding: 20px; background: #fafafa; }
|
|
138
|
+
h1, h2 { text-align: center; }
|
|
139
|
+
table { width: 100%; border-collapse: collapse; margin-top: 20px; }
|
|
140
|
+
th, td { border: 1px solid #ddd; padding: 8px; text-align: left; vertical-align: top; }
|
|
141
|
+
th { background: #f0f0f0; }
|
|
142
|
+
tr:nth-child(even) { background: #f9f9f9; }
|
|
143
|
+
tr:hover { background: #f1f7ff; }
|
|
144
|
+
.status-ok { background: #e6f9e6; color: #207520; }
|
|
145
|
+
.status-near { background: #fff8e1; color: #a87900; }
|
|
146
|
+
.status-exceed { background: #fdecea; color: #b71c1c; }
|
|
147
|
+
code { font-family: monospace; background: #f5f5f5; padding: 1px 3px; border-radius: 3px; }
|
|
148
|
+
details summary { cursor: pointer; }
|
|
149
|
+
.box { border: 1px solid #ccc; background: #fff; padding: 10px; margin: 15px 0; border-radius: 6px; }
|
|
150
|
+
</style>
|
|
151
|
+
</head>
|
|
152
|
+
<body>
|
|
153
|
+
<h1>Performance Budgets Report</h1>
|
|
154
|
+
<div class="box">
|
|
155
|
+
<h2>Medians (Desktop)</h2>
|
|
156
|
+
<p>
|
|
157
|
+
JS: ${medians.jsKb} KB ·
|
|
158
|
+
CSS: ${medians.cssKb} KB ·
|
|
159
|
+
HTML: ${medians.htmlKb} KB ·
|
|
160
|
+
IMG: ${medians.imgKb} KB
|
|
161
|
+
</p>
|
|
162
|
+
<p><b>Links:</b></p>
|
|
163
|
+
<ul>${linksHtml}</ul>
|
|
164
|
+
</div>
|
|
165
|
+
|
|
166
|
+
<div class="box">
|
|
167
|
+
<details open>
|
|
168
|
+
<summary><b>Optimization & Best Practices</b></summary>
|
|
169
|
+
<h3>Tips</h3>
|
|
170
|
+
<ul>${tipsHtml}</ul>
|
|
171
|
+
<h3>Resources</h3>
|
|
172
|
+
<ul>${optimizationHtml}</ul>
|
|
173
|
+
</details>
|
|
174
|
+
</div>
|
|
175
|
+
|
|
176
|
+
<h2>Applications</h2>
|
|
177
|
+
<table>
|
|
178
|
+
<tr>
|
|
179
|
+
<th>App</th>
|
|
180
|
+
<th>JS</th>
|
|
181
|
+
<th>CSS</th>
|
|
182
|
+
<th>HTML</th>
|
|
183
|
+
<th>IMG</th>
|
|
184
|
+
<th>Status</th>
|
|
185
|
+
<th>Details</th>
|
|
186
|
+
</tr>
|
|
187
|
+
${rows}
|
|
188
|
+
</table>
|
|
189
|
+
</body>
|
|
190
|
+
</html>`;
|
|
191
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { PerfBudgetResult } from '../types/PerfBudget.js';
|
|
2
|
+
export declare function evaluateAsset(sizeKb: number, medianKb: number): 'ok' | 'near' | 'exceed';
|
|
3
|
+
export declare function evaluatePerfBudgets(appReport: {
|
|
4
|
+
app: string;
|
|
5
|
+
jsKb: number;
|
|
6
|
+
cssKb: number;
|
|
7
|
+
htmlKb: number;
|
|
8
|
+
imgKb: number;
|
|
9
|
+
}): PerfBudgetResult;
|
|
10
|
+
//# sourceMappingURL=perfs-budgets-rules.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"perfs-budgets-rules.d.ts","sourceRoot":"","sources":["../../../../src/adapters/perf-budgets/rules/perfs-budgets-rules.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAQvD,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,GAAG,QAAQ,CASxF;AAOD,wBAAgB,mBAAmB,CAAC,SAAS,EAAE;IAC7C,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;CACf,GAAG,gBAAgB,CAQnB"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { assetsBudgetsConfig } from '../../../configs/assets-budgets-config.js';
|
|
2
|
+
export function evaluateAsset(sizeKb, medianKb) {
|
|
3
|
+
const { nearFactor, exceedFactor } = assetsBudgetsConfig.thresholds;
|
|
4
|
+
if (sizeKb > medianKb * exceedFactor) {
|
|
5
|
+
return 'exceed';
|
|
6
|
+
}
|
|
7
|
+
else if (sizeKb >= medianKb * nearFactor) {
|
|
8
|
+
return 'near';
|
|
9
|
+
}
|
|
10
|
+
return 'ok';
|
|
11
|
+
}
|
|
12
|
+
export function evaluatePerfBudgets(appReport) {
|
|
13
|
+
return {
|
|
14
|
+
...appReport,
|
|
15
|
+
jsStatus: evaluateAsset(appReport.jsKb, assetsBudgetsConfig.medians.jsKb),
|
|
16
|
+
cssStatus: evaluateAsset(appReport.cssKb, assetsBudgetsConfig.medians.cssKb),
|
|
17
|
+
htmlStatus: evaluateAsset(appReport.htmlKb, assetsBudgetsConfig.medians.htmlKb),
|
|
18
|
+
imgStatus: evaluateAsset(appReport.imgKb, assetsBudgetsConfig.medians.imgKb),
|
|
19
|
+
};
|
|
20
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { PerfBudgetResult } from '../types/PerfBudget.js';
|
|
2
|
+
import { PerfBudgetScoreSummary } from '../types/PerfBudgetScore.js';
|
|
3
|
+
export declare function scorePerfBudget(result: PerfBudgetResult): PerfBudgetScoreSummary;
|
|
4
|
+
export declare function scoreAllPerfBudgets(results: PerfBudgetResult[]): PerfBudgetScoreSummary[];
|
|
5
|
+
//# sourceMappingURL=perfs-budgets-scoring.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"perfs-budgets-scoring.d.ts","sourceRoot":"","sources":["../../../../src/adapters/perf-budgets/rules/perfs-budgets-scoring.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,EAAwB,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAuBxF,wBAAgB,eAAe,CAAC,MAAM,EAAE,gBAAgB,GAAG,sBAAsB,CAqBhF;AAOD,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,gBAAgB,EAAE,GAAG,sBAAsB,EAAE,CAEzF"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
function statusToScore(status) {
|
|
2
|
+
switch (status) {
|
|
3
|
+
case 'ok':
|
|
4
|
+
return 0;
|
|
5
|
+
case 'near':
|
|
6
|
+
return 1;
|
|
7
|
+
case 'exceed':
|
|
8
|
+
return 2;
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
export function scorePerfBudget(result) {
|
|
12
|
+
const scores = {
|
|
13
|
+
js: statusToScore(result.jsStatus),
|
|
14
|
+
css: statusToScore(result.cssStatus),
|
|
15
|
+
html: statusToScore(result.htmlStatus),
|
|
16
|
+
img: statusToScore(result.imgStatus),
|
|
17
|
+
};
|
|
18
|
+
const totalScore = Object.values(scores).reduce((sum, v) => sum + v, 0);
|
|
19
|
+
let status;
|
|
20
|
+
if (totalScore === 0)
|
|
21
|
+
status = 'pass';
|
|
22
|
+
else if (totalScore <= 2)
|
|
23
|
+
status = 'warn';
|
|
24
|
+
else
|
|
25
|
+
status = 'fail';
|
|
26
|
+
return {
|
|
27
|
+
app: result.app,
|
|
28
|
+
scores,
|
|
29
|
+
totalScore,
|
|
30
|
+
status,
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
export function scoreAllPerfBudgets(results) {
|
|
34
|
+
return results.map(scorePerfBudget);
|
|
35
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { assetsBudgetsConfig } from '../../../configs/assets-budgets-config.js';
|
|
2
|
+
import { ParsedAsset } from './PerfBudgetAssets.js';
|
|
3
|
+
import { PerfBudgetScoreSummary } from './PerfBudgetScore.js';
|
|
4
|
+
export interface PerfBudgetResult {
|
|
5
|
+
app: string;
|
|
6
|
+
jsKb: number;
|
|
7
|
+
cssKb: number;
|
|
8
|
+
htmlKb: number;
|
|
9
|
+
imgKb: number;
|
|
10
|
+
jsStatus: 'ok' | 'near' | 'exceed';
|
|
11
|
+
cssStatus: 'ok' | 'near' | 'exceed';
|
|
12
|
+
htmlStatus: 'ok' | 'near' | 'exceed';
|
|
13
|
+
imgStatus: 'ok' | 'near' | 'exceed';
|
|
14
|
+
}
|
|
15
|
+
export interface PerfBudgetsSummary {
|
|
16
|
+
results: (PerfBudgetResult & {
|
|
17
|
+
assets: ParsedAsset[];
|
|
18
|
+
})[];
|
|
19
|
+
scores: PerfBudgetScoreSummary[];
|
|
20
|
+
medians: typeof assetsBudgetsConfig.medians;
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=PerfBudget.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PerfBudget.d.ts","sourceRoot":"","sources":["../../../../src/adapters/perf-budgets/types/PerfBudget.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,wCAAwC,CAAC;AAC7E,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAC;AAK3D,MAAM,WAAW,gBAAgB;IAE/B,GAAG,EAAE,MAAM,CAAC;IAEZ,IAAI,EAAE,MAAM,CAAC;IAEb,KAAK,EAAE,MAAM,CAAC;IAEd,MAAM,EAAE,MAAM,CAAC;IAEf,KAAK,EAAE,MAAM,CAAC;IAGd,QAAQ,EAAE,IAAI,GAAG,MAAM,GAAG,QAAQ,CAAC;IAEnC,SAAS,EAAE,IAAI,GAAG,MAAM,GAAG,QAAQ,CAAC;IAEpC,UAAU,EAAE,IAAI,GAAG,MAAM,GAAG,QAAQ,CAAC;IAErC,SAAS,EAAE,IAAI,GAAG,MAAM,GAAG,QAAQ,CAAC;CACrC;AAgDD,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,CAAC,gBAAgB,GAAG;QAAE,MAAM,EAAE,WAAW,EAAE,CAAA;KAAE,CAAC,EAAE,CAAC;IAC1D,MAAM,EAAE,sBAAsB,EAAE,CAAC;IACjC,OAAO,EAAE,OAAO,mBAAmB,CAAC,OAAO,CAAC;CAC7C"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export interface ParsedAsset {
|
|
2
|
+
filename: string;
|
|
3
|
+
type: 'js' | 'css' | 'html' | 'img' | 'other';
|
|
4
|
+
sizeKb: number;
|
|
5
|
+
}
|
|
6
|
+
export interface ParsedBundle {
|
|
7
|
+
jsKb: number;
|
|
8
|
+
cssKb: number;
|
|
9
|
+
htmlKb: number;
|
|
10
|
+
imgKb: number;
|
|
11
|
+
assets: ParsedAsset[];
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=PerfBudgetAssets.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PerfBudgetAssets.d.ts","sourceRoot":"","sources":["../../../../src/adapters/perf-budgets/types/PerfBudgetAssets.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,WAAW;IAE1B,QAAQ,EAAE,MAAM,CAAC;IAEjB,IAAI,EAAE,IAAI,GAAG,KAAK,GAAG,MAAM,GAAG,KAAK,GAAG,OAAO,CAAC;IAE9C,MAAM,EAAE,MAAM,CAAC;CAChB;AAKD,MAAM,WAAW,YAAY;IAE3B,IAAI,EAAE,MAAM,CAAC;IAEb,KAAK,EAAE,MAAM,CAAC;IAEd,MAAM,EAAE,MAAM,CAAC;IAEf,KAAK,EAAE,MAAM,CAAC;IAEd,MAAM,EAAE,WAAW,EAAE,CAAC;CACvB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export type PerfBudgetScoreLevel = 0 | 1 | 2;
|
|
2
|
+
export interface PerfBudgetScoreSummary {
|
|
3
|
+
app: string;
|
|
4
|
+
scores: {
|
|
5
|
+
js: PerfBudgetScoreLevel;
|
|
6
|
+
css: PerfBudgetScoreLevel;
|
|
7
|
+
html: PerfBudgetScoreLevel;
|
|
8
|
+
img: PerfBudgetScoreLevel;
|
|
9
|
+
};
|
|
10
|
+
totalScore: number;
|
|
11
|
+
status: 'pass' | 'warn' | 'fail';
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=PerfBudgetScore.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PerfBudgetScore.d.ts","sourceRoot":"","sources":["../../../../src/adapters/perf-budgets/types/PerfBudgetScore.ts"],"names":[],"mappings":"AAMA,MAAM,MAAM,oBAAoB,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;AAK7C,MAAM,WAAW,sBAAsB;IAErC,GAAG,EAAE,MAAM,CAAC;IAEZ,MAAM,EAAE;QACN,EAAE,EAAE,oBAAoB,CAAC;QACzB,GAAG,EAAE,oBAAoB,CAAC;QAC1B,IAAI,EAAE,oBAAoB,CAAC;QAC3B,GAAG,EAAE,oBAAoB,CAAC;KAC3B,CAAC;IAEF,UAAU,EAAE,MAAM,CAAC;IAEnB,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,CAAC;CAClC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { CombinedTestsCoverage } from '../types/TestsCoverage.js';
|
|
2
|
+
export declare function collectTestsCoverage(reportRoot: string): CombinedTestsCoverage;
|
|
3
|
+
export declare function generateTestsCoverageHtml(summary: CombinedTestsCoverage, reportRoot: string): string;
|
|
4
|
+
//# sourceMappingURL=tests-coverage-analysis-helper.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tests-coverage-analysis-helper.d.ts","sourceRoot":"","sources":["../../../../src/adapters/tests-coverage/helpers/tests-coverage-analysis-helper.ts"],"names":[],"mappings":"AAIA,OAAO,EACL,qBAAqB,EAKtB,MAAM,wBAAwB,CAAC;AA2HhC,wBAAgB,oBAAoB,CAAC,UAAU,EAAE,MAAM,GAAG,qBAAqB,CAmC9E;AAiED,wBAAgB,yBAAyB,CACvC,OAAO,EAAE,qBAAqB,EAC9B,UAAU,EAAE,MAAM,GACjB,MAAM,CAuER"}
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { testsCoverageConfig } from '../../../configs/tests-coverage-config.js';
|
|
4
|
+
import { TESTS_COVERAGE_KEYS, } from '../types/TestsCoverage.js';
|
|
5
|
+
function readJsonSafe(file) {
|
|
6
|
+
try {
|
|
7
|
+
return JSON.parse(fs.readFileSync(file, 'utf-8'));
|
|
8
|
+
}
|
|
9
|
+
catch {
|
|
10
|
+
return null;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
function readAppSummaryAt(reportRoot, app) {
|
|
14
|
+
return readJsonSafe(path.join(reportRoot, app, 'coverage-summary.json'));
|
|
15
|
+
}
|
|
16
|
+
function normalizePct(pct) {
|
|
17
|
+
const n = Number(pct);
|
|
18
|
+
if (!Number.isFinite(n) || n < 0)
|
|
19
|
+
return 0;
|
|
20
|
+
return +n.toFixed(2);
|
|
21
|
+
}
|
|
22
|
+
function extractWorstFilesForApp(reportRoot, app, metric = testsCoverageConfig.worstFiles.metric, threshold = testsCoverageConfig.worstFiles.threshold, count = testsCoverageConfig.worstFiles.count) {
|
|
23
|
+
const summary = readAppSummaryAt(reportRoot, app);
|
|
24
|
+
if (!summary)
|
|
25
|
+
return [];
|
|
26
|
+
const rows = [];
|
|
27
|
+
for (const [key, value] of Object.entries(summary)) {
|
|
28
|
+
if (key === 'total')
|
|
29
|
+
continue;
|
|
30
|
+
const bucket = value?.[metric];
|
|
31
|
+
if (!bucket)
|
|
32
|
+
continue;
|
|
33
|
+
const total = bucket.total ?? 0;
|
|
34
|
+
const covered = bucket.covered ?? 0;
|
|
35
|
+
if (!Number.isFinite(total) || total <= 0)
|
|
36
|
+
continue;
|
|
37
|
+
const percentage = normalizePct(bucket.pct);
|
|
38
|
+
if (percentage >= threshold)
|
|
39
|
+
continue;
|
|
40
|
+
rows.push([key, { covered, total, percentage }]);
|
|
41
|
+
}
|
|
42
|
+
rows.sort((a, b) => a[1].percentage - b[1].percentage || b[1].total - a[1].total || a[0].localeCompare(b[0]));
|
|
43
|
+
return rows.slice(0, Math.max(0, count));
|
|
44
|
+
}
|
|
45
|
+
function addTotals(a, b) {
|
|
46
|
+
const out = {};
|
|
47
|
+
for (const k of TESTS_COVERAGE_KEYS) {
|
|
48
|
+
const A = a[k] ?? { total: 0, covered: 0, pct: 0 };
|
|
49
|
+
const B = b[k] ?? { total: 0, covered: 0, pct: 0 };
|
|
50
|
+
const total = (A.total ?? 0) + (B.total ?? 0);
|
|
51
|
+
const covered = (A.covered ?? 0) + (B.covered ?? 0);
|
|
52
|
+
out[k] = {
|
|
53
|
+
total,
|
|
54
|
+
covered,
|
|
55
|
+
pct: total > 0 ? normalizePct((100 * covered) / total) : 0,
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
return out;
|
|
59
|
+
}
|
|
60
|
+
export function collectTestsCoverage(reportRoot) {
|
|
61
|
+
if (!fs.existsSync(reportRoot))
|
|
62
|
+
return { apps: {}, totals: undefined };
|
|
63
|
+
const appDirs = (() => {
|
|
64
|
+
try {
|
|
65
|
+
return fs
|
|
66
|
+
.readdirSync(reportRoot, { withFileTypes: true })
|
|
67
|
+
.filter((d) => d.isDirectory())
|
|
68
|
+
.map((d) => d.name);
|
|
69
|
+
}
|
|
70
|
+
catch {
|
|
71
|
+
return [];
|
|
72
|
+
}
|
|
73
|
+
})();
|
|
74
|
+
const apps = {};
|
|
75
|
+
let totals;
|
|
76
|
+
for (const app of appDirs) {
|
|
77
|
+
const summary = readAppSummaryAt(reportRoot, app);
|
|
78
|
+
const total = summary?.total;
|
|
79
|
+
if (!total)
|
|
80
|
+
continue;
|
|
81
|
+
const row = {};
|
|
82
|
+
for (const k of TESTS_COVERAGE_KEYS) {
|
|
83
|
+
const g = total[k];
|
|
84
|
+
row[k] = g
|
|
85
|
+
? { total: g.total ?? 0, covered: g.covered ?? 0, pct: normalizePct(g.pct) }
|
|
86
|
+
: { total: 0, covered: 0, pct: 0 };
|
|
87
|
+
}
|
|
88
|
+
apps[app] = row;
|
|
89
|
+
totals = totals ? addTotals(totals, row) : row;
|
|
90
|
+
}
|
|
91
|
+
return { apps, totals };
|
|
92
|
+
}
|
|
93
|
+
function getTestsCoverageStatusColor(pct) {
|
|
94
|
+
const { green, orange } = testsCoverageConfig.thresholds;
|
|
95
|
+
if (pct >= green)
|
|
96
|
+
return 'green';
|
|
97
|
+
if (pct >= orange)
|
|
98
|
+
return 'orange';
|
|
99
|
+
return 'red';
|
|
100
|
+
}
|
|
101
|
+
function renderWorstFiles(app, worst) {
|
|
102
|
+
const { threshold, metric } = testsCoverageConfig.worstFiles;
|
|
103
|
+
if (!worst.length) {
|
|
104
|
+
return `
|
|
105
|
+
<details>
|
|
106
|
+
<summary>⚠️ Worst covered files (${metric})</summary>
|
|
107
|
+
<p style="margin:0.5rem 0; color:#888;">No files below threshold 🎉</p>
|
|
108
|
+
</details>`;
|
|
109
|
+
}
|
|
110
|
+
const rows = worst
|
|
111
|
+
.map(([file, f]) => `
|
|
112
|
+
<tr>
|
|
113
|
+
<td colspan="2">${file}</td>
|
|
114
|
+
<td>${f.covered}/${f.total}</td>
|
|
115
|
+
<td style="color:${getTestsCoverageStatusColor(f.percentage)}">${f.percentage.toFixed(2)}%</td>
|
|
116
|
+
</tr>`)
|
|
117
|
+
.join('');
|
|
118
|
+
return `
|
|
119
|
+
<details>
|
|
120
|
+
<summary>⚠️ Worst covered files (below ${threshold}% — ${metric})</summary>
|
|
121
|
+
<table style="margin:0.5rem 0; border:1px solid #ccc; width:95%;">
|
|
122
|
+
<tbody>${rows}</tbody>
|
|
123
|
+
</table>
|
|
124
|
+
</details>`;
|
|
125
|
+
}
|
|
126
|
+
export function generateTestsCoverageHtml(summary, reportRoot) {
|
|
127
|
+
const head = `
|
|
128
|
+
<style>
|
|
129
|
+
body { font-family: Arial, sans-serif; margin: 2rem; }
|
|
130
|
+
h1 { margin-bottom: 1rem; }
|
|
131
|
+
table { border-collapse: collapse; width: 100%; margin-bottom: 2rem; }
|
|
132
|
+
th, td { border: 1px solid #ccc; padding: 0.5rem; text-align: left; vertical-align: top; }
|
|
133
|
+
th { background: #f0f0f0; }
|
|
134
|
+
details summary { cursor: pointer; font-weight: bold; }
|
|
135
|
+
.green { color: #0a0; }
|
|
136
|
+
.orange { color: #c80; }
|
|
137
|
+
.red { color: #c00; }
|
|
138
|
+
.row-green { background:#e6ffed; }
|
|
139
|
+
.row-orange { background:#fff8e1; }
|
|
140
|
+
.row-red { background:#ffe6e6; }
|
|
141
|
+
</style>
|
|
142
|
+
<h1>Tests Coverage</h1>
|
|
143
|
+
`;
|
|
144
|
+
const appRow = (app, r) => {
|
|
145
|
+
const status = getTestsCoverageStatusColor(r.lines?.pct ?? 0);
|
|
146
|
+
return `
|
|
147
|
+
<tr class="row-${status}">
|
|
148
|
+
<td>${app}</td>
|
|
149
|
+
${TESTS_COVERAGE_KEYS.map((k) => {
|
|
150
|
+
const pct = r[k]?.pct ?? 0;
|
|
151
|
+
const cls = getTestsCoverageStatusColor(pct);
|
|
152
|
+
return `<td class="${cls}" style="font-weight:600">${pct}%</td>`;
|
|
153
|
+
}).join('')}
|
|
154
|
+
</tr>
|
|
155
|
+
<tr>
|
|
156
|
+
<td colspan="5">
|
|
157
|
+
${renderWorstFiles(app, extractWorstFilesForApp(reportRoot, app))}
|
|
158
|
+
</td>
|
|
159
|
+
</tr>
|
|
160
|
+
`;
|
|
161
|
+
};
|
|
162
|
+
const totalsRow = summary.totals
|
|
163
|
+
? `
|
|
164
|
+
<tr>
|
|
165
|
+
<td><b>Totals</b></td>
|
|
166
|
+
${TESTS_COVERAGE_KEYS.map((k) => {
|
|
167
|
+
const pct = summary.totals?.[k]?.pct ?? 0;
|
|
168
|
+
const cls = getTestsCoverageStatusColor(pct);
|
|
169
|
+
return `<td class="${cls}"><b>${pct}%</b></td>`;
|
|
170
|
+
}).join('')}
|
|
171
|
+
</tr>`
|
|
172
|
+
: '';
|
|
173
|
+
const table = `
|
|
174
|
+
<table>
|
|
175
|
+
<thead>
|
|
176
|
+
<tr>
|
|
177
|
+
<th>Application</th>
|
|
178
|
+
<th>Lines %</th>
|
|
179
|
+
<th>Branches %</th>
|
|
180
|
+
<th>Functions %</th>
|
|
181
|
+
<th>Statements %</th>
|
|
182
|
+
</tr>
|
|
183
|
+
</thead>
|
|
184
|
+
<tbody>
|
|
185
|
+
${Object.entries(summary.apps)
|
|
186
|
+
.map(([app, r]) => appRow(app, r))
|
|
187
|
+
.join('')}
|
|
188
|
+
${totalsRow}
|
|
189
|
+
</tbody>
|
|
190
|
+
</table>`;
|
|
191
|
+
return `<!doctype html><meta charset="utf-8">${head}${table}`;
|
|
192
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
export type TestsCoverageKey = 'lines' | 'branches' | 'functions' | 'statements';
|
|
2
|
+
export declare const TESTS_COVERAGE_KEYS: readonly TestsCoverageKey[];
|
|
3
|
+
export interface TestsCoverageBucket {
|
|
4
|
+
total: number;
|
|
5
|
+
covered: number;
|
|
6
|
+
pct: number;
|
|
7
|
+
}
|
|
8
|
+
export type TestsCoverageRow = Record<TestsCoverageKey, TestsCoverageBucket>;
|
|
9
|
+
export interface CombinedTestsCoverage {
|
|
10
|
+
apps: Record<string, TestsCoverageRow>;
|
|
11
|
+
totals?: TestsCoverageRow;
|
|
12
|
+
}
|
|
13
|
+
export interface TestsCoverageSummary {
|
|
14
|
+
total?: Partial<Record<TestsCoverageKey, Partial<TestsCoverageBucket>>>;
|
|
15
|
+
}
|
|
16
|
+
export type TestsCoverageMetric = keyof TestsCoverageRow;
|
|
17
|
+
export interface WorstFilesOptions {
|
|
18
|
+
reportRoot: string;
|
|
19
|
+
count: number;
|
|
20
|
+
metric: TestsCoverageMetric;
|
|
21
|
+
}
|
|
22
|
+
export interface FileCoverageRow {
|
|
23
|
+
file: string;
|
|
24
|
+
total: number;
|
|
25
|
+
covered: number;
|
|
26
|
+
pct: number;
|
|
27
|
+
}
|
|
28
|
+
export type WorstFileEntry = readonly [
|
|
29
|
+
file: string,
|
|
30
|
+
stats: {
|
|
31
|
+
covered: number;
|
|
32
|
+
total: number;
|
|
33
|
+
percentage: number;
|
|
34
|
+
}
|
|
35
|
+
];
|
|
36
|
+
//# sourceMappingURL=TestsCoverage.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TestsCoverage.d.ts","sourceRoot":"","sources":["../../../../src/adapters/tests-coverage/types/TestsCoverage.ts"],"names":[],"mappings":"AAKA,MAAM,MAAM,gBAAgB,GAAG,OAAO,GAAG,UAAU,GAAG,WAAW,GAAG,YAAY,CAAC;AAOjF,eAAO,MAAM,mBAAmB,EAAE,SAAS,gBAAgB,EAKjD,CAAC;AAOX,MAAM,WAAW,mBAAmB;IAElC,KAAK,EAAE,MAAM,CAAC;IAEd,OAAO,EAAE,MAAM,CAAC;IAEhB,GAAG,EAAE,MAAM,CAAC;CACb;AAOD,MAAM,MAAM,gBAAgB,GAAG,MAAM,CAAC,gBAAgB,EAAE,mBAAmB,CAAC,CAAC;AAQ7E,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC;IACvC,MAAM,CAAC,EAAE,gBAAgB,CAAC;CAC3B;AAmBD,MAAM,WAAW,oBAAoB;IAEnC,KAAK,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,gBAAgB,EAAE,OAAO,CAAC,mBAAmB,CAAC,CAAC,CAAC,CAAC;CACzE;AAMD,MAAM,MAAM,mBAAmB,GAAG,MAAM,gBAAgB,CAAC;AAKzD,MAAM,WAAW,iBAAiB;IAEhC,UAAU,EAAE,MAAM,CAAC;IAEnB,KAAK,EAAE,MAAM,CAAC;IAEd,MAAM,EAAE,mBAAmB,CAAC;CAC7B;AAOD,MAAM,WAAW,eAAe;IAE9B,IAAI,EAAE,MAAM,CAAC;IAEb,KAAK,EAAE,MAAM,CAAC;IAEd,OAAO,EAAE,MAAM,CAAC;IAEhB,GAAG,EAAE,MAAM,CAAC;CACb;AAQD,MAAM,MAAM,cAAc,GAAG,SAAS;IACpC,IAAI,EAAE,MAAM;IACZ,KAAK,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE;CAC9D,CAAC"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { CoverageSummary } from '../types/TypesCoverage.js';
|
|
2
|
+
export declare function collectTypesCoverage(reportOutputDir: string): CoverageSummary;
|
|
3
|
+
export declare function generateTypesCoverageHtml(summary: CoverageSummary): string;
|
|
4
|
+
//# sourceMappingURL=types-coverage-analysis-helper.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types-coverage-analysis-helper.d.ts","sourceRoot":"","sources":["../../../../src/adapters/types-coverage/helpers/types-coverage-analysis-helper.ts"],"names":[],"mappings":"AAIA,OAAO,EAEL,eAAe,EAGhB,MAAM,wBAAwB,CAAC;AAoChC,wBAAgB,oBAAoB,CAAC,eAAe,EAAE,MAAM,GAAG,eAAe,CAkD7E;AA6ED,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,eAAe,GAAG,MAAM,CAgC1E"}
|