feat(05-02): add lagoon.Validate rule-string engine

- Translate Laravel rule strings onto validator.Var and unique:table
- Custom money range via big.Rat; unique checks skip soft-deleted rows
- Fill zeros nil values and Scans jsonable columns
This commit is contained in:
Jakub Zych
2026-09-18 19:22:04 +02:00
parent 20b0199579
commit 2c5d92d659
5 changed files with 490 additions and 12 deletions

View File

@@ -1,6 +1,8 @@
package lagoon
import (
"database/sql"
"encoding/json"
"fmt"
"log/slog"
"reflect"
@@ -95,8 +97,11 @@ func setField(field reflect.Value, val any) error {
return fmt.Errorf("field cannot be set")
}
if val == nil {
if field.Kind() == reflect.Ptr {
field.Set(reflect.Zero(field.Type()))
field.Set(reflect.Zero(field.Type()))
if field.CanAddr() {
if scanner, ok := field.Addr().Interface().(sql.Scanner); ok {
return scanner.Scan(nil)
}
}
return nil
}
@@ -113,11 +118,33 @@ func setField(field reflect.Value, val any) error {
return nil
}
converted, err := convertValue(src, field.Type())
if err != nil {
return err
if err == nil {
field.Set(converted)
return nil
}
if field.CanAddr() {
if scanner, ok := field.Addr().Interface().(sql.Scanner); ok {
scanSrc, scanErr := fillScanSource(val)
if scanErr != nil {
return scanErr
}
return scanner.Scan(scanSrc)
}
}
return err
}
func fillScanSource(val any) (any, error) {
switch v := val.(type) {
case string, []byte:
return v, nil
default:
b, err := json.Marshal(v)
if err != nil {
return nil, err
}
return b, nil
}
field.Set(converted)
return nil
}
func convertValue(src reflect.Value, destType reflect.Type) (reflect.Value, error) {