-
Notifications
You must be signed in to change notification settings - Fork 136
Expand file tree
/
Copy pathcheck-helpers.ts
More file actions
142 lines (121 loc) · 4.48 KB
/
Copy pathcheck-helpers.ts
File metadata and controls
142 lines (121 loc) · 4.48 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
// altimate_change start — check-helpers: extracted helpers for deterministic SQL check command
// These are exported separately so they can be unit-tested without importing
// the full CLI command (which has side-effects via yargs).
// ---------------------------------------------------------------------------
// Types
// ---------------------------------------------------------------------------
export interface Finding {
file: string
line?: number
column?: number
code?: string
rule?: string
severity: "error" | "warning" | "info"
message: string
suggestion?: string
}
export interface CheckCategoryResult {
findings: Finding[]
error_count: number
warning_count: number
[key: string]: unknown
}
export interface CheckOutput {
version: 1
files_checked: number
checks_run: string[]
schema_resolved: boolean
results: Record<string, CheckCategoryResult>
summary: {
total_findings: number
errors: number
warnings: number
info: number
pass: boolean
}
}
export type Severity = "error" | "warning" | "info"
export const SEVERITY_RANK: Record<Severity, number> = { error: 2, warning: 1, info: 0 }
export const VALID_CHECKS = new Set(["lint", "validate", "safety", "policy", "pii", "semantic", "grade"])
// ---------------------------------------------------------------------------
// Helpers
// ---------------------------------------------------------------------------
export function normalizeSeverity(s?: string | unknown): Severity {
if (!s || typeof s !== "string") return "warning"
const lower = s.toLowerCase()
if (lower === "error" || lower === "fatal" || lower === "critical") return "error"
if (lower === "warning" || lower === "warn") return "warning"
return "info"
}
export function filterBySeverity(findings: Finding[], minSeverity: Severity): Finding[] {
const minRank = SEVERITY_RANK[minSeverity]
return findings.filter((f) => SEVERITY_RANK[f.severity] >= minRank)
}
export function toCategoryResult(findings: Finding[]): CheckCategoryResult {
return {
findings,
error_count: findings.filter((f) => f.severity === "error").length,
warning_count: findings.filter((f) => f.severity === "warning").length,
}
}
// ---------------------------------------------------------------------------
// Text formatter
// ---------------------------------------------------------------------------
export function formatText(output: CheckOutput): string {
const lines: string[] = []
lines.push(`Checked ${output.files_checked} file(s) with [${output.checks_run.join(", ")}]`)
if (output.schema_resolved) {
lines.push("Schema: resolved")
}
lines.push("")
for (const [category, catResult] of Object.entries(output.results)) {
if (catResult.findings.length === 0) continue
lines.push(`--- ${category.toUpperCase()} ---`)
for (const f of catResult.findings) {
const loc = f.line ? `:${f.line}${f.column ? `:${f.column}` : ""}` : ""
const rule = f.rule ? ` [${f.rule}]` : ""
lines.push(` ${f.severity.toUpperCase()} ${f.file}${loc}${rule}: ${f.message}`)
if (f.suggestion) {
lines.push(` suggestion: ${f.suggestion}`)
}
}
lines.push("")
}
const s = output.summary
lines.push(`${s.total_findings} finding(s): ${s.errors} error(s), ${s.warnings} warning(s), ${s.info} info`)
lines.push(s.pass ? "PASS" : "FAIL")
return lines.join("\n")
}
// ---------------------------------------------------------------------------
// Output builder
// ---------------------------------------------------------------------------
export function buildCheckOutput(opts: {
filesChecked: number
checksRun: string[]
schemaResolved: boolean
results: Record<string, CheckCategoryResult>
failOn: "none" | "warning" | "error"
}): CheckOutput {
const allFindings = Object.values(opts.results).flatMap((r) => r.findings)
const errors = allFindings.filter((f) => f.severity === "error").length
const warnings = allFindings.filter((f) => f.severity === "warning").length
const info = allFindings.filter((f) => f.severity === "info").length
let pass = true
if (opts.failOn === "error" && errors > 0) pass = false
if (opts.failOn === "warning" && (errors > 0 || warnings > 0)) pass = false
return {
version: 1,
files_checked: opts.filesChecked,
checks_run: opts.checksRun,
schema_resolved: opts.schemaResolved,
results: opts.results,
summary: {
total_findings: allFindings.length,
errors,
warnings,
info,
pass,
},
}
}
// altimate_change end