@@ -11,6 +11,7 @@ import (
1111 "unicode"
1212
1313 "github.com/cloudquery/plugin-sdk/schema"
14+ "github.com/grpc-ecosystem/go-grpc-middleware/providers/zerolog/v2"
1415 "github.com/iancoleman/strcase"
1516)
1617
@@ -19,9 +20,11 @@ type TableOptions func(*TableDefinition)
1920//go:embed templates/*.go.tpl
2021var TemplatesFS embed.FS
2122
22- func valueToSchemaType (v reflect.Type ) (schema.ValueType , error ) {
23+ func DefaultGoTypeToSchemaType (v reflect.Type ) (schema.ValueType , error ) {
2324 k := v .Kind ()
2425 switch k {
26+ case reflect .Pointer :
27+ return DefaultGoTypeToSchemaType (v .Elem ())
2528 case reflect .String :
2629 return schema .TypeString , nil
2730 case reflect .Bool :
@@ -39,8 +42,6 @@ func valueToSchemaType(v reflect.Type) (schema.ValueType, error) {
3942 return schema .TypeTimestamp , nil
4043 }
4144 return schema .TypeJSON , nil
42- case reflect .Pointer :
43- return valueToSchemaType (v .Elem ())
4445 case reflect .Slice :
4546 switch v .Elem ().Kind () {
4647 case reflect .String :
@@ -56,7 +57,11 @@ func valueToSchemaType(v reflect.Type) (schema.ValueType, error) {
5657 }
5758}
5859
59- func WithNameTransformer (transformer func (field reflect.StructField ) string ) TableOptions {
60+ func DefaultTypeTransformer (v reflect.StructField ) (schema.ValueType , error ) {
61+ return DefaultGoTypeToSchemaType (v .Type )
62+ }
63+
64+ func WithNameTransformer (transformer NameTransformer ) TableOptions {
6065 return func (t * TableDefinition ) {
6166 t .nameTransformer = transformer
6267 }
@@ -81,23 +86,37 @@ func WithUnwrapFieldsStructs(fields []string) TableOptions {
8186 }
8287}
8388
84- // Unwrap all fields that are embedded structs (1 level deep only)
89+ // WithUnwrapAllEmbeddedStructs unwraps all fields that are embedded structs (1 level deep only)
8590func WithUnwrapAllEmbeddedStructs () TableOptions {
8691 return func (t * TableDefinition ) {
8792 t .unwrapAllEmbeddedStructFields = true
8893 }
8994}
9095
91- func DefaultTransformer (field reflect.StructField ) string {
96+ // WithLogger
97+ func WithLogger (logger zerolog.Logger ) TableOptions {
98+ return func (t * TableDefinition ) {
99+ t .logger = logger
100+ }
101+ }
102+
103+ // WithValueTypeTransformer sets a function that can override the schema type for specific fields. Return `schema.TypeInvalid` to fall back to default behavior.
104+ func WithTypeTransformer (transformer TypeTransformer ) TableOptions {
105+ return func (t * TableDefinition ) {
106+ t .typeTransformer = transformer
107+ }
108+ }
109+
110+ func DefaultTransformer (field reflect.StructField ) (string , error ) {
92111 name := field .Name
93112 if jsonTag := strings .Split (field .Tag .Get ("json" ), "," )[0 ]; len (jsonTag ) > 0 {
94113 // return empty string if the field is not related api response
95114 if jsonTag == "-" {
96- return ""
115+ return "" , nil
97116 }
98117 name = jsonTag
99118 }
100- return strcase .ToSnake (name )
119+ return strcase .ToSnake (name ), nil
101120}
102121
103122func sliceContains (arr []string , s string ) bool {
@@ -139,27 +158,40 @@ func (t *TableDefinition) ignoreField(field reflect.StructField) bool {
139158 return len (field .Name ) == 0 || unicode .IsLower (rune (field .Name [0 ])) || sliceContains (t .skipFields , field .Name )
140159}
141160
142- func (t * TableDefinition ) addColumnFromField (field reflect.StructField , parent * reflect.StructField ) {
161+ func (t * TableDefinition ) addColumnFromField (field reflect.StructField , parent * reflect.StructField ) error {
143162 if t .ignoreField (field ) {
144- return
163+ return nil
145164 }
146165
147- columnType , err := valueToSchemaType (field . Type )
166+ columnType , err := t . typeTransformer (field )
148167 if err != nil {
149- fmt .Printf ("skipping field %s on table %s, got err: %v\n " , field .Name , t .Name , err )
150- return
168+ return fmt .Errorf ("failed to transform type for field %s: %w" , field .Name , err )
169+ }
170+
171+ if columnType == schema .TypeInvalid {
172+ columnType , err = DefaultTypeTransformer (field )
173+ if err != nil {
174+ return fmt .Errorf ("failed to transform type for field %s: %w" , field .Name , err )
175+ }
151176 }
152177
153178 // generate a PathResolver to use by default
154179 pathResolver := fmt .Sprintf (`schema.PathResolver("%s")` , field .Name )
155- name := t .nameTransformer (field )
180+ name , err := t .nameTransformer (field )
181+ if err != nil {
182+ return fmt .Errorf ("failed to transform field name for field %s: %w" , field .Name , err )
183+ }
156184 // skip field if there is no name
157185 if name == "" {
158- return
186+ return nil
159187 }
160188 if parent != nil {
161189 pathResolver = fmt .Sprintf (`schema.PathResolver("%s.%s")` , parent .Name , field .Name )
162- name = t .nameTransformer (* parent ) + "_" + name
190+ parentName , err := t .nameTransformer (* parent )
191+ if err != nil {
192+ return fmt .Errorf ("failed to transform field name for parent field %s: %w" , parent .Name , err )
193+ }
194+ name = fmt .Sprintf ("%s_%s" , parentName , name )
163195 }
164196
165197 column := ColumnDefinition {
@@ -168,13 +200,15 @@ func (t *TableDefinition) addColumnFromField(field reflect.StructField, parent *
168200 Resolver : pathResolver ,
169201 }
170202 t .Columns = append (t .Columns , column )
203+ return nil
171204}
172205
173206// NewTableFromStruct creates a new TableDefinition from a struct by inspecting its fields
174207func NewTableFromStruct (name string , obj interface {}, opts ... TableOptions ) (* TableDefinition , error ) {
175208 t := & TableDefinition {
176209 Name : name ,
177210 nameTransformer : DefaultTransformer ,
211+ typeTransformer : DefaultTypeTransformer ,
178212 }
179213 for _ , opt := range opts {
180214 opt (t )
@@ -201,10 +235,14 @@ func NewTableFromStruct(name string, obj interface{}, opts ...TableOptions) (*Ta
201235 parent = & field
202236 }
203237 for _ , f := range unwrappedFields {
204- t .addColumnFromField (f , parent )
238+ if err := t .addColumnFromField (f , parent ); err != nil {
239+ return nil , fmt .Errorf ("failed to add column from field %s: %w" , f .Name , err )
240+ }
205241 }
206242 } else {
207- t .addColumnFromField (field , nil )
243+ if err := t .addColumnFromField (field , nil ); err != nil {
244+ return nil , fmt .Errorf ("failed to add column for field %s: %w" , field .Name , err )
245+ }
208246 }
209247 }
210248
0 commit comments