add validation

This commit is contained in:
Grigoryev Ilya Alekseevich
2026-04-01 00:50:06 +05:00
parent 6745820f71
commit 03f2eeef09
6 changed files with 117 additions and 3 deletions

View File

@@ -1,7 +1,9 @@
package cmd
import (
"errors"
"fmt"
"reflect"
"strings"
)
@@ -111,3 +113,99 @@ func ValidateLeaf(cmd any) error {
return nil
}
}
// Валидация путей.
// Принимает на вход объект и при наличии метода Enabled производит валидацию
func ValidatePath(cmd any) error {
switch v := cmd.(type) {
case interface{ Enabled() error }:
return v.Enabled()
default:
return nil
}
}
// Проверяет, что у команды с output-блоками включён хотя бы один вывод.
func ValidateOutput(cmd any) error {
if cmd == nil {
return nil
}
v := reflect.ValueOf(cmd)
if v.Kind() == reflect.Pointer {
if v.IsNil() {
return nil
}
v = v.Elem()
}
if v.Kind() != reflect.Struct {
return nil
}
var hasOutputBlocks bool
var hasEnabledOutput bool
for i := 0; i < v.NumField(); i++ {
field := v.Field(i)
fieldType := v.Type().Field(i)
switch fieldType.Type {
case reflect.TypeOf(CSVOutput{}):
hasOutputBlocks = true
if enabled, ok := callEnabled(field); ok && enabled {
hasEnabledOutput = true
}
case reflect.TypeOf(JSONOutput{}):
hasOutputBlocks = true
if enabled, ok := callEnabled(field); ok && enabled {
hasEnabledOutput = true
}
case reflect.TypeOf(BodyOutput{}):
hasOutputBlocks = true
if enabled, ok := callEnabled(field); ok && enabled {
hasEnabledOutput = true
}
}
}
if hasOutputBlocks && !hasEnabledOutput {
return errors.New("you must specify at least one output path: --csv, --json or --body")
}
return nil
}
// Вызов Enabled у поля
// Возвращает результат Enabled() и флаг успешности поиска метода
func callEnabled(v reflect.Value) (bool, bool) {
if !v.IsValid() {
return false, false
}
// Пробуем метод у самого значения
if method := v.MethodByName("Enabled"); method.IsValid() {
if method.Type().NumIn() == 0 &&
method.Type().NumOut() == 1 &&
method.Type().Out(0).Kind() == reflect.Bool {
out := method.Call(nil)
return out[0].Bool(), true
}
}
// Пробуем метод у указателя
if v.CanAddr() {
if method := v.Addr().MethodByName("Enabled"); method.IsValid() {
if method.Type().NumIn() == 0 &&
method.Type().NumOut() == 1 &&
method.Type().Out(0).Kind() == reflect.Bool {
out := method.Call(nil)
return out[0].Bool(), true
}
}
}
return false, false
}