@hublo/sentinel 1.5.0-alpha.10 → 1.5.0-alpha.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/bin/sentinel.js
CHANGED
|
@@ -4864,6 +4864,16 @@ function helpFor(key) {
|
|
|
4864
4864
|
}
|
|
4865
4865
|
|
|
4866
4866
|
// src/roles/static-analysis/report.ts
|
|
4867
|
+
var SCRIPTS = { json: "static-analysis:json", html: "static-analysis:html" };
|
|
4868
|
+
function secondSide(finding) {
|
|
4869
|
+
if (!finding.other) return "";
|
|
4870
|
+
const file = (at) => at.split(":")[0] ?? at;
|
|
4871
|
+
const sameFile = file(finding.other) === file(finding.path);
|
|
4872
|
+
const label = sameFile ? "and line" : "and";
|
|
4873
|
+
const shownSide = sameFile ? finding.other.split(":")[1] ?? finding.other : finding.other;
|
|
4874
|
+
return ` <span class="unit">${label}</span> <code>${escape(shownSide)}</code>`;
|
|
4875
|
+
}
|
|
4876
|
+
var HTML_GROUP_LIMIT = 50;
|
|
4867
4877
|
function shown(row) {
|
|
4868
4878
|
return row.unit === "%" && typeof row.value === "number" ? row.value.toFixed(2) : String(row.value);
|
|
4869
4879
|
}
|
|
@@ -4900,6 +4910,12 @@ function renderConsole(report) {
|
|
|
4900
4910
|
}
|
|
4901
4911
|
lines.push(" a language is absent when no file of it was long enough to scan");
|
|
4902
4912
|
}
|
|
4913
|
+
if (report.findings.length > 0) {
|
|
4914
|
+
lines.push(
|
|
4915
|
+
"",
|
|
4916
|
+
` ${report.findings.length} place(s) to look, listed by \`${SCRIPTS.json}\` and \`${SCRIPTS.html}\``
|
|
4917
|
+
);
|
|
4918
|
+
}
|
|
4903
4919
|
const caveats = report.rows.map((row) => ({ row, help: helpFor(row.metric) })).filter(
|
|
4904
4920
|
(entry) => Boolean(entry.help)
|
|
4905
4921
|
);
|
|
@@ -4937,6 +4953,36 @@ function renderHtml(report) {
|
|
|
4937
4953
|
<td>${setting.moved ? '<span class="moved">overridden in this module</span>' : ""}</td>
|
|
4938
4954
|
</tr>`
|
|
4939
4955
|
).join("\n");
|
|
4956
|
+
const groups = /* @__PURE__ */ new Map();
|
|
4957
|
+
for (const finding of report.findings) {
|
|
4958
|
+
const bucket = groups.get(finding.metric) ?? [];
|
|
4959
|
+
bucket.push(finding);
|
|
4960
|
+
groups.set(finding.metric, bucket);
|
|
4961
|
+
}
|
|
4962
|
+
const findings = [...groups.entries()].map(([metric, all2]) => {
|
|
4963
|
+
const label = helpFor(metric)?.label ?? metric;
|
|
4964
|
+
const sorted = [...all2].sort((a, b) => (b.lines ?? 0) - (a.lines ?? 0));
|
|
4965
|
+
const shown2 = sorted.slice(0, HTML_GROUP_LIMIT);
|
|
4966
|
+
const rest = sorted.length - shown2.length;
|
|
4967
|
+
const rows2 = shown2.map(
|
|
4968
|
+
(finding) => ` <tr>
|
|
4969
|
+
<td><code>${escape(finding.path)}</code>${secondSide(finding)}</td>
|
|
4970
|
+
<td>${finding.name ? `<code>${escape(finding.name)}</code>` : ""}</td>
|
|
4971
|
+
<td class="num">${finding.lines ?? ""}</td>
|
|
4972
|
+
<td class="num">${finding.confidence ?? ""}</td>
|
|
4973
|
+
</tr>`
|
|
4974
|
+
).join("\n");
|
|
4975
|
+
return ` <h2>${escape(label)}: where to look</h2>
|
|
4976
|
+
<table>
|
|
4977
|
+
<thead>
|
|
4978
|
+
<tr><th scope="col">File</th><th scope="col">Name</th><th scope="col">Lines</th><th scope="col">Confidence</th></tr>
|
|
4979
|
+
</thead>
|
|
4980
|
+
<tbody>
|
|
4981
|
+
${rows2}
|
|
4982
|
+
</tbody>
|
|
4983
|
+
</table>
|
|
4984
|
+
${rest > 0 ? ` <p class="sub">The ${HTML_GROUP_LIMIT} longest are listed; ${rest} more are in <code>${SCRIPTS.json}</code>.</p>` : ""}`;
|
|
4985
|
+
}).join("\n");
|
|
4940
4986
|
return `<!doctype html>
|
|
4941
4987
|
<html lang="en">
|
|
4942
4988
|
<head>
|
|
@@ -4985,6 +5031,7 @@ ${rows}
|
|
|
4985
5031
|
${settings}
|
|
4986
5032
|
</tbody>
|
|
4987
5033
|
</table>
|
|
5034
|
+
${findings}
|
|
4988
5035
|
</main>
|
|
4989
5036
|
</body>
|
|
4990
5037
|
</html>
|
|
@@ -5403,7 +5450,7 @@ ${result.stderr ?? ""}`
|
|
|
5403
5450
|
const category = finding.category ?? "unknown";
|
|
5404
5451
|
byCategory[category] = (byCategory[category] ?? 0) + 1;
|
|
5405
5452
|
}
|
|
5406
|
-
return { kind: "figures", statistics, byCategory };
|
|
5453
|
+
return { kind: "figures", statistics, byCategory, findings: parsed.findings ?? [] };
|
|
5407
5454
|
} finally {
|
|
5408
5455
|
dispose();
|
|
5409
5456
|
}
|
|
@@ -5437,7 +5484,12 @@ ${result.stderr ?? ""}`
|
|
|
5437
5484
|
);
|
|
5438
5485
|
return { kind: "failed", code: 1 };
|
|
5439
5486
|
}
|
|
5440
|
-
return {
|
|
5487
|
+
return {
|
|
5488
|
+
kind: "figures",
|
|
5489
|
+
total,
|
|
5490
|
+
formats: parsed?.statistics?.formats ?? {},
|
|
5491
|
+
duplicates: parsed?.duplicates ?? []
|
|
5492
|
+
};
|
|
5441
5493
|
} finally {
|
|
5442
5494
|
dispose();
|
|
5443
5495
|
}
|
|
@@ -5449,6 +5501,32 @@ function safeParse(text) {
|
|
|
5449
5501
|
return void 0;
|
|
5450
5502
|
}
|
|
5451
5503
|
}
|
|
5504
|
+
function placesToLook(product, tests, dead) {
|
|
5505
|
+
const at = (side) => `${side?.name ?? "(unknown)"}${side?.start === void 0 ? "" : `:${side.start}`}`;
|
|
5506
|
+
const clones = (outcome, metric) => outcome.kind === "figures" ? outcome.duplicates.map((entry) => ({
|
|
5507
|
+
metric,
|
|
5508
|
+
path: at(entry.firstFile),
|
|
5509
|
+
other: at(entry.secondFile),
|
|
5510
|
+
...entry.lines === void 0 ? {} : { lines: entry.lines }
|
|
5511
|
+
})) : [];
|
|
5512
|
+
const deadMetric = {
|
|
5513
|
+
"unused-file": "unusedFiles",
|
|
5514
|
+
"unused-export": "unusedExports",
|
|
5515
|
+
"unused-symbol": "unusedSymbols",
|
|
5516
|
+
"unused-import": "unusedImports"
|
|
5517
|
+
};
|
|
5518
|
+
return [
|
|
5519
|
+
...clones(product, "clones"),
|
|
5520
|
+
...clones(tests, "clonesTests"),
|
|
5521
|
+
...dead.kind === "figures" ? dead.findings.map((finding) => ({
|
|
5522
|
+
metric: deadMetric[finding.category ?? ""] ?? "deadLinesPercent",
|
|
5523
|
+
path: finding.path ?? "(unknown)",
|
|
5524
|
+
...finding.name ? { name: finding.name } : {},
|
|
5525
|
+
...finding.lines === void 0 ? {} : { lines: finding.lines },
|
|
5526
|
+
...finding.confidence === void 0 ? {} : { confidence: finding.confidence }
|
|
5527
|
+
})) : []
|
|
5528
|
+
];
|
|
5529
|
+
}
|
|
5452
5530
|
function assemble(ctx, config, product, tests, dead) {
|
|
5453
5531
|
const share = (total) => Number((total.percentage ?? 0).toFixed(2));
|
|
5454
5532
|
const rows = [
|
|
@@ -5508,6 +5586,7 @@ function assemble(ctx, config, product, tests, dead) {
|
|
|
5508
5586
|
rows,
|
|
5509
5587
|
notes,
|
|
5510
5588
|
settings: duplicationSettings(config),
|
|
5589
|
+
findings: placesToLook(product, tests, dead),
|
|
5511
5590
|
byLanguage
|
|
5512
5591
|
};
|
|
5513
5592
|
}
|
package/dist/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hublo/sentinel",
|
|
3
|
-
"version": "1.5.0-alpha.
|
|
3
|
+
"version": "1.5.0-alpha.12",
|
|
4
4
|
"description": "One CLI that guards code health across Hublo repos: shared lint/typescript/build/test presets, static & dynamic analysis, and architecture checks.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|