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  }