Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 8 additions & 46 deletions generator/generator.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,19 +23,14 @@ type templateData struct {
DefaultDiskPath string
Schema schema.Schema
DefaultLogs []string
NeedCUID bool
NeedCUID2 bool
NeedUUID bool
NeedUUID7 bool
NeedULID bool
NeedNanoID bool
}

type modelTemplateData struct {
PackageName string
Model *schema.Model
ParentImportPath string
ParentPackageName string
Schema schema.Schema
}

func ResolveImportPath(clientDir string) (string, error) {
Expand Down Expand Up @@ -111,50 +106,21 @@ func GenerateClient(sch schema.Schema, pkgName string, parentImportPath string,
"fieldPredType": fieldPredType,
"hasLog": hasLog,
"hasAnyLog": hasAnyLog,
"hasJsonField": hasJsonField,
"hasJsonAnywhere": hasJsonAnywhere,
"hasTimeField": hasTimeField,
"hasTimeAnywhere": hasTimeAnywhere,
"hasType": hasType,
"hasModelType": hasModelType,
"trimPrefix": strings.TrimPrefix,
"isKnownDefaultFunc": isKnownDefaultFunc,
"defaultFuncCall": defaultFuncCall,
"hasHstoreAnywhere": hasHstoreAnywhere,
"hasNetAnywhere": hasNetAnywhere,
"hasUuidAnywhere": hasUuidAnywhere,
"hasFloatAnywhere": hasFloatAnywhere,
"hasDecimalAnywhere": hasDecimalAnywhere,
"isPostgresProvider": isPostgresProvider,
"needsPQImport": needsPQImport,
"hasDefaultFunc": hasDefaultFunc,
"hstoreExpr": hstoreExpr,
})
tmpl, err := tmpl.ParseFS(templatesFS, "templates/*.gotpl")
if err != nil {
return nil, err
}

var needCUID, needUUID, needUUID7, needCUID2, needULID, needNanoID bool
for _, m := range sch.Models {
for _, sf := range m.ScalarFields {
if sf.Default != nil && sf.Default.Kind == schema.DefaultFunc {
switch sf.Default.FuncName {
case "cuid", "cuid(1)":
needCUID = true
case "cuid(2)":
needCUID2 = true
case "uuid", "uuid(4)":
needUUID = true
case "uuid(7)":
needUUID7 = true
case "ulid":
needULID = true
case "nanoid":
needNanoID = true
}
}
if sf.IsID && sf.GoType == "string" && sf.Default == nil {
needCUID = true
}
}
}

var embedDir string
if embedPath != "" {
embedDir = filepath.ToSlash(filepath.Dir(embedPath))
Expand All @@ -167,12 +133,6 @@ func GenerateClient(sch schema.Schema, pkgName string, parentImportPath string,
DefaultDiskPath: defaultDiskPath,
Schema: sch,
DefaultLogs: defaultLogs,
NeedCUID: needCUID,
NeedCUID2: needCUID2,
NeedUUID: needUUID,
NeedUUID7: needUUID7,
NeedULID: needULID,
NeedNanoID: needNanoID,
}

outputs := make(map[string]string)
Expand Down Expand Up @@ -210,6 +170,7 @@ func GenerateClient(sch schema.Schema, pkgName string, parentImportPath string,
Model: m,
ParentImportPath: parentImportPath,
ParentPackageName: pkgName,
Schema: sch,
}

if err := tmpl.ExecuteTemplate(&mBuf, "model_header.gotpl", mData); err != nil {
Expand Down Expand Up @@ -244,6 +205,7 @@ func GenerateClient(sch schema.Schema, pkgName string, parentImportPath string,
Model: m,
ParentImportPath: parentImportPath,
ParentPackageName: pkgName,
Schema: sch,
}
if err := tmpl.ExecuteTemplate(&pBuf, "model_predicate.gotpl", pData); err != nil {
return nil, err
Expand Down
114 changes: 59 additions & 55 deletions generator/helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"slices"
"strings"

providers "github.com/voidclancy/valk/dbProviders"
"github.com/voidclancy/valk/schema"
)

Expand Down Expand Up @@ -66,26 +67,45 @@ func fieldPredType(f *schema.ScalarField, parentPkg string) string {
return t
}

func hasFieldWhere(m *schema.Model, pred func(*schema.ScalarField) bool) bool {
return slices.ContainsFunc(m.ScalarFields, pred)
func hasModelType(m *schema.Model, targetTypes ...string) bool {
for _, sf := range m.ScalarFields {
for _, t := range targetTypes {
switch t {
case "Array":
if sf.IsArray {
return true
}
case "Hstore":
if strings.Contains(sf.GoType, "map[string]*string") {
return true
}
case "DateTime", "Time":
if sf.Type == "DateTime" || strings.Contains(sf.GoType, "time.Time") {
return true
}
case "Json":
if (sf.Type == "Json" || strings.Contains(sf.GoType, "json.RawMessage")) && !sf.IsArray {
return true
}
default:
if sf.Type == t || (sf.NativeType != nil && sf.NativeType.Name == t) {
return true
}
}
}
}
return false
}

func hasJsonField(m *schema.Model) bool {
return hasFieldWhere(m, func(sf *schema.ScalarField) bool {
return sf.Type == "Json" || strings.Contains(sf.GoType, "json.RawMessage")
})
}
func hasJsonAnywhere(sch schema.Schema) bool {
return slices.ContainsFunc(sch.Models, hasJsonField)
}
func hasTimeField(m *schema.Model) bool {
return hasFieldWhere(m, func(sf *schema.ScalarField) bool {
return sf.Type == "DateTime" || strings.Contains(sf.GoType, "time.Time")
})
}
func hasTimeAnywhere(sch schema.Schema) bool {
return slices.ContainsFunc(sch.Models, hasTimeField)
func hasType(sch schema.Schema, targetTypes ...string) bool {
for _, m := range sch.Models {
if hasModelType(m, targetTypes...) {
return true
}
}
return false
}

func isKnownDefaultFunc(funcName string) bool {
val, ok := DEFAULT_FUNCS[funcName]
return ok && val != ""
Expand All @@ -94,45 +114,29 @@ func isKnownDefaultFunc(funcName string) bool {
func defaultFuncCall(funcName string) string {
return DEFAULT_FUNCS[funcName]
}
func hasUuidField(m *schema.Model) bool {
return hasFieldWhere(m, func(sf *schema.ScalarField) bool {
return sf.NativeType != nil && sf.NativeType.Name == "Uuid"
})
}
func hasUuidAnywhere(sch schema.Schema) bool {
return slices.ContainsFunc(sch.Models, hasUuidField)
}
func hasFloatField(m *schema.Model) bool {
return hasFieldWhere(m, func(sf *schema.ScalarField) bool {
return sf.Type == "Float"
})
}
func hasFloatAnywhere(sch schema.Schema) bool {
return slices.ContainsFunc(sch.Models, hasFloatField)
}
func hasDecimalField(m *schema.Model) bool {
return hasFieldWhere(m, func(sf *schema.ScalarField) bool {
return sf.Type == "Decimal"
})
}
func hasDecimalAnywhere(sch schema.Schema) bool {
return slices.ContainsFunc(sch.Models, hasDecimalField)
}
func hasNetField(m *schema.Model) bool {
return hasFieldWhere(m, func(sf *schema.ScalarField) bool {
return sf.NativeType != nil && sf.NativeType.Name == "Inet"
})
}
func hasNetAnywhere(sch schema.Schema) bool {
return slices.ContainsFunc(sch.Models, hasNetField)
}
func hasHstoreField(m *schema.Model) bool {
return hasFieldWhere(m, func(sf *schema.ScalarField) bool {
return strings.TrimPrefix(sf.GoType, "*") == "map[string]*string"
})

func isPostgresProvider(sch schema.Schema) bool {
p := sch.Datasource.Provider
return p == providers.Postgres || p == providers.Postgresql
}
func hasHstoreAnywhere(sch schema.Schema) bool {
return slices.ContainsFunc(sch.Models, hasHstoreField)

func needsPQImport(sch schema.Schema) bool {
return isPostgresProvider(sch) && hasType(sch, "Array")
}
func hasDefaultFunc(sch schema.Schema, names ...string) bool {
for _, m := range sch.Models {
for _, sf := range m.ScalarFields {
if sf.Default != nil && sf.Default.Kind == schema.DefaultFunc {
if slices.Contains(names, sf.Default.FuncName) {
return true
}
}
if sf.IsID && sf.GoType == "string" && sf.Default == nil && slices.Contains(names, "cuid") {
return true
}
}
}
return false
}
func hstoreExpr(goType string, expr string) string {
if strings.TrimPrefix(goType, "*") == "map[string]*string" {
Expand Down
Loading
Loading