initial commit

This commit is contained in:
m.zare
2026-04-10 18:25:21 +03:30
commit 77ca6c34a3
263 changed files with 34470 additions and 0 deletions

79
pkg/helper/struct.go Normal file
View File

@@ -0,0 +1,79 @@
package helper
import (
"encoding/json"
"fmt"
"reflect"
"strings"
)
func MapToStruct(source map[string]interface{}, target interface{}) error {
jsonBytes, err := json.Marshal(source)
if err != nil {
return err
}
err = json.Unmarshal(jsonBytes, target)
if err != nil {
return err
}
return nil
}
// StructToMap converts a struct to a map[string]interface{}
// Uses json tag name as key when available, so keys match validation schema (e.g. "provider" not "Provider")
// does not support nested structs
func StructToMap(v any) map[string]interface{} {
result := make(map[string]interface{})
val := reflect.ValueOf(v)
typ := reflect.TypeOf(v)
if val.Kind() == reflect.Ptr {
val = val.Elem()
typ = typ.Elem()
}
for i := 0; i < val.NumField(); i++ {
field := typ.Field(i)
value := val.Field(i)
// Skip unexported fields
if !value.CanInterface() {
continue
}
key := field.Name
if tag := field.Tag.Get("json"); tag != "" {
// Use first part before comma (e.g. "provider,omitempty" -> "provider")
if name := strings.TrimSpace(strings.Split(tag, ",")[0]); name != "" && name != "-" {
key = name
}
}
fieldVal := value.Interface()
// If type implements String(), use it so validation gets string (e.g. oauth.Provider -> "mock")
// Use reflect to detect nil pointer - s != nil passes for interface holding (*T)(nil)
if s, ok := fieldVal.(fmt.Stringer); ok {
if isNilValue(value) {
result[key] = fieldVal // keep nil/zero for optional fields
} else {
result[key] = s.String()
}
} else {
result[key] = fieldVal
}
}
return result
}
// isNilValue returns true if v is nil (ptr, slice, map, chan, func, interface).
// Used to avoid calling String() on nil receivers (e.g. *uuid.UUID).
func isNilValue(v reflect.Value) bool {
switch v.Kind() {
case reflect.Ptr, reflect.Slice, reflect.Map, reflect.Chan, reflect.Func, reflect.Interface:
return v.IsNil()
default:
return false
}
}