fix(bun): support extra generated model fields

This commit is contained in:
Hermes Agent
2026-07-09 05:50:33 +02:00
parent 7805d9b6f0
commit 47b77763cb
7 changed files with 359 additions and 2 deletions
+86
View File
@@ -1,6 +1,8 @@
package bun
import (
"encoding/json"
"fmt"
"sort"
"strings"
@@ -32,6 +34,90 @@ type ModelData struct {
PrimaryKeyIDType string // Helper method GetID/SetID/UpdateID type
IDColumnName string // Name of the ID column in database
Prefix string // 3-letter prefix
// ExtraFields are user-defined fields added via generator config (issue #4)
ExtraFields []*FieldData `json:"extra_fields,omitempty"`
}
// ExtraFieldConfig represents a custom field to be added to generated models
type ExtraFieldConfig struct {
Name string `json:"name"`
Type string `json:"type"`
BunTag string `json:"bun_tag,omitempty"`
JSONTag string `json:"json_tag,omitempty"`
Comment string `json:"comment,omitempty"`
TargetTable string `json:"target_table,omitempty"` // optional: if set, field only applies to this table
}
// LoadExtraFieldsFromMetadata loads custom field configurations from metadata map.
// Accepts either a JSON-encoded array of fields (for CLI use) or a structured list
// (for programmatic/sidecar file use). Each entry must have "name" and "type";
// an optional "target_table" scopes the field to one table only.
func LoadExtraFieldsFromMetadata(metadata map[string]interface{}) []ExtraFieldConfig {
if metadata == nil {
return nil
}
extraFieldsRaw, ok := metadata["extra_fields"]
if !ok || extraFieldsRaw == nil {
return nil
}
// Try to parse as JSON string first (from CLI flag)
if strVal, ok := extraFieldsRaw.(string); ok {
var fields []ExtraFieldConfig
if err := json.Unmarshal([]byte(strVal), &fields); err == nil && len(fields) > 0 {
return filterValidFields(fields)
}
}
// Try to parse as structured data (from sidecar file or programmatic API)
extraFieldsList, ok := extraFieldsRaw.([]interface{})
if !ok || len(extraFieldsList) == 0 {
return nil
}
fields := make([]ExtraFieldConfig, 0, len(extraFieldsList))
for _, item := range extraFieldsList {
if fieldMap, ok := item.(map[string]interface{}); ok {
field := ExtraFieldConfig{
Name: toString(fieldMap["name"]),
Type: toString(fieldMap["type"]),
BunTag: toString(fieldMap["bun_tag"]),
JSONTag: toString(fieldMap["json_tag"]),
Comment: toString(fieldMap["comment"]),
TargetTable: toString(fieldMap["target_table"]),
}
if field.Name != "" && field.Type != "" {
fields = append(fields, field)
}
}
}
return filterValidFields(fields)
}
// filterValidFields removes entries that are missing required fields.
func filterValidFields(fields []ExtraFieldConfig) []ExtraFieldConfig {
var valid []ExtraFieldConfig
for _, f := range fields {
if f.Name != "" && f.Type != "" {
valid = append(valid, f)
}
}
return valid
}
func toString(v interface{}) string {
if v == nil {
return ""
}
switch val := v.(type) {
case string:
return val
default:
return fmt.Sprintf("%v", val)
}
}
// FieldData represents a single field in a struct