github.com/Ali-iotechsys/sqlboiler/v4@v4.0.0-20221208124957-6aec9a5f1f71/boilingcore/config.go (about) 1 package boilingcore 2 3 import ( 4 "io/fs" 5 "path/filepath" 6 "strings" 7 "text/template" 8 9 "github.com/spf13/cast" 10 11 "github.com/volatiletech/sqlboiler/v4/drivers" 12 "github.com/volatiletech/sqlboiler/v4/importers" 13 ) 14 15 // Config for the running of the commands 16 type Config struct { 17 DriverName string `toml:"driver_name,omitempty" json:"driver_name,omitempty"` 18 DriverConfig drivers.Config `toml:"driver_config,omitempty" json:"driver_config,omitempty"` 19 20 PkgName string `toml:"pkg_name,omitempty" json:"pkg_name,omitempty"` 21 OutFolder string `toml:"out_folder,omitempty" json:"out_folder,omitempty"` 22 TemplateDirs []string `toml:"template_dirs,omitempty" json:"template_dirs,omitempty"` 23 Tags []string `toml:"tags,omitempty" json:"tags,omitempty"` 24 Replacements []string `toml:"replacements,omitempty" json:"replacements,omitempty"` 25 Debug bool `toml:"debug,omitempty" json:"debug,omitempty"` 26 AddGlobal bool `toml:"add_global,omitempty" json:"add_global,omitempty"` 27 AddPanic bool `toml:"add_panic,omitempty" json:"add_panic,omitempty"` 28 AddSoftDeletes bool `toml:"add_soft_deletes,omitempty" json:"add_soft_deletes,omitempty"` 29 AddEnumTypes bool `toml:"add_enum_types,omitempty" json:"add_enum_types,omitempty"` 30 EnumNullPrefix string `toml:"enum_null_prefix,omitempty" json:"enum_null_prefix,omitempty"` 31 NoContext bool `toml:"no_context,omitempty" json:"no_context,omitempty"` 32 NoTests bool `toml:"no_tests,omitempty" json:"no_tests,omitempty"` 33 NoHooks bool `toml:"no_hooks,omitempty" json:"no_hooks,omitempty"` 34 NoAutoTimestamps bool `toml:"no_auto_timestamps,omitempty" json:"no_auto_timestamps,omitempty"` 35 NoRowsAffected bool `toml:"no_rows_affected,omitempty" json:"no_rows_affected,omitempty"` 36 NoDriverTemplates bool `toml:"no_driver_templates,omitempty" json:"no_driver_templates,omitempty"` 37 NoBackReferencing bool `toml:"no_back_reference,omitempty" json:"no_back_reference,omitempty"` 38 AlwaysWrapErrors bool `toml:"always_wrap_errors,omitempty" json:"always_wrap_errors,omitempty"` 39 Wipe bool `toml:"wipe,omitempty" json:"wipe,omitempty"` 40 StructTagCasing string `toml:"struct_tag_casing,omitempty" json:"struct_tag_casing,omitempty"` 41 RelationTag string `toml:"relation_tag,omitempty" json:"relation_tag,omitempty"` 42 TagIgnore []string `toml:"tag_ignore,omitempty" json:"tag_ignore,omitempty"` 43 44 Imports importers.Collection `toml:"imports,omitempty" json:"imports,omitempty"` 45 46 DefaultTemplates fs.FS `toml:"-" json:"-"` 47 CustomTemplateFuncs template.FuncMap `toml:"-" json:"-"` 48 49 Aliases Aliases `toml:"aliases,omitempty" json:"aliases,omitempty"` 50 TypeReplaces []TypeReplace `toml:"type_replaces,omitempty" json:"type_replaces,omitempty"` 51 AutoColumns AutoColumns `toml:"auto_columns,omitempty" json:"auto_columns,omitempty"` 52 Inflections Inflections `toml:"inflections,omitempty" json:"inflections,omitempty"` 53 54 Version string `toml:"version" json:"version"` 55 } 56 57 type AutoColumns struct { 58 Created string `toml:"created,omitempty" json:"created,omitempty"` 59 Updated string `toml:"updated,omitempty" json:"updated,omitempty"` 60 Deleted string `toml:"deleted,omitempty" json:"deleted,omitempty"` 61 } 62 63 // TypeReplace replaces a column type with something else 64 type TypeReplace struct { 65 Tables []string `toml:"tables,omitempty" json:"tables,omitempty"` 66 Views []string `toml:"views,omitempty" json:"views,omitempty"` 67 Match drivers.Column `toml:"match,omitempty" json:"match,omitempty"` 68 Replace drivers.Column `toml:"replace,omitempty" json:"replace,omitempty"` 69 Imports importers.Set `toml:"imports,omitempty" json:"imports,omitempty"` 70 } 71 72 type Inflections struct { 73 Plural map[string]string 74 PluralExact map[string]string 75 Singular map[string]string 76 SingularExact map[string]string 77 Irregular map[string]string 78 } 79 80 // OutputDirDepth returns depth of output directory 81 func (c *Config) OutputDirDepth() int { 82 d := filepath.ToSlash(filepath.Clean(c.OutFolder)) 83 if d == "." { 84 return 0 85 } 86 87 return strings.Count(d, "/") + 1 88 } 89 90 // ConvertAliases is necessary because viper 91 // 92 // It also supports two different syntaxes, because of viper: 93 // 94 // [aliases.tables.table_name] 95 // fields... = "values" 96 // [aliases.tables.columns] 97 // colname = "alias" 98 // [aliases.tables.relationships.fkey_name] 99 // local = "x" 100 // foreign = "y" 101 // 102 // Or alternatively (when toml key names or viper's 103 // lowercasing of key names gets in the way): 104 // 105 // [[aliases.tables]] 106 // name = "table_name" 107 // fields... = "values" 108 // [[aliases.tables.columns]] 109 // name = "colname" 110 // alias = "alias" 111 // [[aliases.tables.relationships]] 112 // name = "fkey_name" 113 // local = "x" 114 // foreign = "y" 115 func ConvertAliases(i interface{}) (a Aliases) { 116 if i == nil { 117 return a 118 } 119 120 topLevel := cast.ToStringMap(i) 121 122 tablesIntf := topLevel["tables"] 123 124 iterateMapOrSlice(tablesIntf, func(name string, tIntf interface{}) { 125 if a.Tables == nil { 126 a.Tables = make(map[string]TableAlias) 127 } 128 129 t := cast.ToStringMap(tIntf) 130 131 var ta TableAlias 132 133 if s := t["up_plural"]; s != nil { 134 ta.UpPlural = s.(string) 135 } 136 if s := t["up_singular"]; s != nil { 137 ta.UpSingular = s.(string) 138 } 139 if s := t["down_plural"]; s != nil { 140 ta.DownPlural = s.(string) 141 } 142 if s := t["down_singular"]; s != nil { 143 ta.DownSingular = s.(string) 144 } 145 146 if colsIntf, ok := t["columns"]; ok { 147 ta.Columns = make(map[string]string) 148 149 iterateMapOrSlice(colsIntf, func(name string, colIntf interface{}) { 150 var alias string 151 switch col := colIntf.(type) { 152 case map[string]interface{}, map[interface{}]interface{}: 153 cmap := cast.ToStringMap(colIntf) 154 alias = cmap["alias"].(string) 155 case string: 156 alias = col 157 } 158 ta.Columns[name] = alias 159 }) 160 } 161 162 relationshipsIntf, ok := t["relationships"] 163 if ok { 164 iterateMapOrSlice(relationshipsIntf, func(name string, rIntf interface{}) { 165 if ta.Relationships == nil { 166 ta.Relationships = make(map[string]RelationshipAlias) 167 } 168 169 var ra RelationshipAlias 170 rel := cast.ToStringMap(rIntf) 171 172 if s := rel["local"]; s != nil { 173 ra.Local = s.(string) 174 } 175 if s := rel["foreign"]; s != nil { 176 ra.Foreign = s.(string) 177 } 178 179 ta.Relationships[name] = ra 180 }) 181 } 182 183 a.Tables[name] = ta 184 }) 185 186 return a 187 } 188 189 func iterateMapOrSlice(mapOrSlice interface{}, fn func(name string, obj interface{})) { 190 switch t := mapOrSlice.(type) { 191 case map[string]interface{}, map[interface{}]interface{}: 192 tmap := cast.ToStringMap(mapOrSlice) 193 for name, table := range tmap { 194 fn(name, table) 195 } 196 case []interface{}: 197 for _, intf := range t { 198 obj := cast.ToStringMap(intf) 199 name := obj["name"].(string) 200 fn(name, intf) 201 } 202 } 203 } 204 205 // ConvertTypeReplace is necessary because viper 206 func ConvertTypeReplace(i interface{}) []TypeReplace { 207 if i == nil { 208 return nil 209 } 210 211 intfArray := i.([]interface{}) 212 var replaces []TypeReplace 213 for _, r := range intfArray { 214 replaceIntf := cast.ToStringMap(r) 215 replace := TypeReplace{} 216 217 if replaceIntf["match"] == nil || replaceIntf["replace"] == nil { 218 panic("replace types must specify both match and replace") 219 } 220 221 replace.Match = columnFromInterface(replaceIntf["match"]) 222 replace.Replace = columnFromInterface(replaceIntf["replace"]) 223 224 replace.Tables = tablesOfTypeReplace(replaceIntf["match"]) 225 226 if imps := replaceIntf["imports"]; imps != nil { 227 imps = cast.ToStringMap(imps) 228 var err error 229 replace.Imports, err = importers.SetFromInterface(imps) 230 if err != nil { 231 panic(err) 232 } 233 } 234 235 replaces = append(replaces, replace) 236 } 237 238 return replaces 239 } 240 241 func tablesOfTypeReplace(i interface{}) []string { 242 tables := []string{} 243 244 m := cast.ToStringMap(i) 245 if s := m["tables"]; s != nil { 246 tables = cast.ToStringSlice(s) 247 } 248 249 return tables 250 } 251 252 func columnFromInterface(i interface{}) (col drivers.Column) { 253 m := cast.ToStringMap(i) 254 if s := m["name"]; s != nil { 255 col.Name = s.(string) 256 } 257 if s := m["type"]; s != nil { 258 col.Type = s.(string) 259 } 260 if s := m["db_type"]; s != nil { 261 col.DBType = s.(string) 262 } 263 if s := m["udt_name"]; s != nil { 264 col.UDTName = s.(string) 265 } 266 if s := m["full_db_type"]; s != nil { 267 col.FullDBType = s.(string) 268 } 269 if s := m["arr_type"]; s != nil { 270 col.ArrType = new(string) 271 *col.ArrType = s.(string) 272 } 273 if s := m["domain_name"]; s != nil { 274 col.DomainName = new(string) 275 *col.DomainName = s.(string) 276 } 277 if b := m["auto_generated"]; b != nil { 278 col.AutoGenerated = b.(bool) 279 } 280 if b := m["nullable"]; b != nil { 281 col.Nullable = b.(bool) 282 } 283 284 return col 285 }