Validate: Human-readable error messages

This commit is contained in:
Yorhel 2025-03-06 10:16:12 +01:00
parent e4b6b77e1b
commit e5755ddd80
3 changed files with 79 additions and 56 deletions

View file

@ -321,8 +321,10 @@ sub _validate {
sub validate($c, $input) {
my $r = _validate($c, $input);
return $input if !$r;
die bless $r, 'FU::Validate::err';
$input
$r = bless $r, 'FU::Validate::err';;
my @e = $r->errors;
$r->{longmess} = Carp::longmess(@e > 1 ? join("\n",@e)."\n" : $e[0]);
die $r;
}
@ -330,12 +332,31 @@ sub validate($c, $input) {
package FU::Validate::err;
use v5.36;
use FU::Util;
use overload '""' => sub {
# TODO: Better error message
require Data::Dumper;
Data::Dumper->new([{$_[0]->%*}])->Terse(1)->Pair(':')->Indent(0)->Sortkeys(1)->Dump."\n";
};
use overload '""' => sub { $_[0]{longmess} || join "\n", $_[0]->errors };
sub _fmtkey($k) {
$k =~ /^[a-zA-Z0-9_-]+$/ ? $k : FU::Util::json_format($k);
}
sub _fmtval($v) {
eval { $v = FU::Util::json_format($v) }; "$v"
}
sub errors($e, $prefix='') {
my $val = $e->{validation};
my $p = $prefix ? "$prefix: " : '';
$val eq 'keys' ? map errors($_, $prefix.'.'._fmtkey($_->{key})), $e->{errors}->@* :
$val eq 'missing' ? $prefix.'.'._fmtkey($e->{key}).': required key missing' :
$val eq 'values' ? map errors($_, $prefix."[$_->{index}]"), $e->{errors}->@* :
$val eq 'unique' ? $prefix."[$e->{index_b}] value '"._fmtval($e->{value_a})."' duplicated" :
$val eq 'required' ? "${p}required value missing" :
$val eq 'type' ? "${p}invalid type, expected '$e->{expected}' but got '$e->{got}'" :
$val eq 'unknown' ? ($e->{keys}->@* > 1 ? "${p}unknown keys: ".join(', ', _fmtkey($e->{keys})) : "${p}unknown key '"._fmtkey($e->{keys}[0])."'") :
$e->{error} ? errors($e->{error}, "${p}validation '$val'") :
"${p}failed validation '$val'";
}
1;