Validate: Improved + extendable error message formatting
Very much needed for VNDB's advanced search validation. Also completely undocumented.
This commit is contained in:
parent
461ed6f39d
commit
753cac615a
2 changed files with 48 additions and 33 deletions
|
|
@ -395,32 +395,47 @@ sub empty($c) {
|
|||
|
||||
|
||||
|
||||
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 _inval($t,$v) { sprintf 'invalid %s: %s', $t, _fmtval $v }
|
||||
|
||||
# validation name => formatting sub
|
||||
# TODO: document.
|
||||
our %error_format = (
|
||||
required => sub { 'required value missing' },
|
||||
type => sub($e) { "invalid type, expected '$e->{expected}' but got '$e->{got}'" },
|
||||
unknown => sub($e) { sprintf 'unknown key%s: %s', $e->{keys}->@* == 1 ? '' : 's', join ', ', map _fmtkey($_), $e->{keys}->@* },
|
||||
minlength => sub($e) { sprintf "input too short, expected minimum of %d but got %d", $e->{expected}, $e->{got} },
|
||||
maxlength => sub($e) { sprintf "input too long, expected maximum of %d but got %d", $e->{expected}, $e->{got} },
|
||||
length => sub($e) {
|
||||
!ref $e->{expected}
|
||||
? sprintf 'invalid input length, expected %d but got %d', $e->{expected}, $e->{got}
|
||||
: sprintf 'invalid input length, expected between %d and %d but got %d', $e->{expected}->@*, $e->{got}
|
||||
},
|
||||
num => sub($e) { _inval 'number', $e->{got} },
|
||||
min => sub($e) { $e->{error} ? _inval 'number', $e->{error}{got} : sprintf 'expected minimum %s but got %s', $e->{expected}, $e->{got} },
|
||||
max => sub($e) { $e->{error} ? _inval 'number', $e->{error}{got} : sprintf 'expected maximum %s but got %s', $e->{expected}, $e->{got} },
|
||||
range => sub($e) { FU::Validate::err::errors($e->{error}) },
|
||||
);
|
||||
|
||||
|
||||
package FU::Validate::err;
|
||||
use v5.36;
|
||||
use FU::Util;
|
||||
|
||||
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"
|
||||
}
|
||||
|
||||
# TODO: document.
|
||||
sub errors($e, $prefix='') {
|
||||
my $val = $e->{validation};
|
||||
my $p = $prefix ? "$prefix: " : '';
|
||||
$val eq 'keys' ? map errors($_, $prefix.'.'._fmtkey($_->{key})), $e->{errors}->@* :
|
||||
$val eq 'values' ? map errors($_, $prefix.'.'._fmtkey($_->{key})), $e->{errors}->@* :
|
||||
$val eq 'missing' ? $prefix.'.'._fmtkey($e->{key}).': required key missing' :
|
||||
$FU::Validate::error_format{$val} ? map "$p$_", $FU::Validate::error_format{$val}->($e) :
|
||||
$val eq 'keys' ? map errors($_, $prefix.'.'.FU::Validate::_fmtkey($_->{key})), $e->{errors}->@* :
|
||||
$val eq 'values' ? map errors($_, $prefix.'.'.FU::Validate::_fmtkey($_->{key})), $e->{errors}->@* :
|
||||
$val eq 'missing' ? $prefix.'.'.FU::Validate::_fmtkey($e->{key}).': required key missing' :
|
||||
$val eq 'elems' ? 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])."'") :
|
||||
$val eq 'unique' ? $prefix."[$e->{index_b}] value '".FU::Validate::_fmtval($e->{value_a})."' duplicated" :
|
||||
$e->{error} ? errors($e->{error}, "${p}validation '$val'") :
|
||||
$e->{message} ? "${p}validation '$val': $e->{message}" :
|
||||
"${p}failed validation '$val'";
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue