super-graph/core/graph-schema.go

175 lines
4.5 KiB
Go
Raw Normal View History

package core
import (
"strings"
"github.com/chirino/graphql"
"github.com/chirino/graphql/resolvers"
"github.com/chirino/graphql/schema"
"github.com/dosco/super-graph/core/internal/psql"
)
var typeMap map[string]string = map[string]string{
"smallint": "Int",
"integer": "Int",
"bigint": "Int",
"smallserial": "Int",
"serial": "Int",
"bigserial": "Int",
"decimal": "Float",
"numeric": "Float",
"real": "Float",
"double precision": "Float",
"money": "Float",
"boolean": "Boolean",
}
func (sg *SuperGraph) initGraphQLEgine() error {
sg.Engine = graphql.New()
engineSchema := sg.Engine.Schema
dbSchema := sg.schema
sanitizeForGraphQLSchema := func(value string) string {
// TODO:
return value
}
gqltype := func(col psql.DBColumn) schema.Type {
typeName := typeMap[strings.ToLower(col.Type)]
if typeName == "" {
typeName = "String"
}
var t schema.Type = &schema.TypeName{Ident: schema.Ident{Text: typeName}}
if col.NotNull {
t = &schema.NonNull{OfType: t}
}
return t
}
query := &schema.Object{
Name: "Query",
Fields: schema.FieldList{},
}
mutation := &schema.Object{
Name: "Mutation",
Fields: schema.FieldList{},
}
engineSchema.Types[query.Name] = query
engineSchema.Types[mutation.Name] = mutation
engineSchema.EntryPoints[schema.Query] = query
engineSchema.EntryPoints[schema.Mutation] = mutation
tableNames := dbSchema.GetTableNames()
for _, table := range tableNames {
ti, err := dbSchema.GetTable(table)
if err != nil {
return err
}
if !ti.IsSingular {
continue
}
pti, err := dbSchema.GetTable(ti.Plural)
if err != nil {
return err
}
outputType := &schema.Object{
Name: sanitizeForGraphQLSchema(ti.Singular) + "Output",
Fields: schema.FieldList{},
}
inputType := &schema.InputObject{
Name: sanitizeForGraphQLSchema(ti.Singular) + "Input",
Fields: schema.InputValueList{},
}
for _, col := range ti.Columns {
outputType.Fields = append(outputType.Fields, &schema.Field{
Name: sanitizeForGraphQLSchema(col.Name),
Type: gqltype(col),
})
inputType.Fields = append(inputType.Fields, &schema.InputValue{
Name: schema.Ident{Text: sanitizeForGraphQLSchema(col.Name)},
Type: gqltype(col),
})
}
engineSchema.Types[outputType.Name] = outputType
engineSchema.Types[inputType.Name] = inputType
outputTypeName := &schema.TypeName{Ident: schema.Ident{Text: outputType.Name}}
inputTypeName := &schema.TypeName{Ident: schema.Ident{Text: inputType.Name}}
pluralOutputTypeName := &schema.NonNull{OfType: &schema.List{OfType: &schema.NonNull{OfType: &schema.TypeName{Ident: schema.Ident{Text: outputType.Name}}}}}
pluralInputTypeName := &schema.NonNull{OfType: &schema.List{OfType: &schema.NonNull{OfType: &schema.TypeName{Ident: schema.Ident{Text: inputType.Name}}}}}
args := schema.InputValueList{}
if ti.PrimaryCol != nil {
t := gqltype(*ti.PrimaryCol)
if _, ok := t.(*schema.NonNull); !ok {
t = &schema.NonNull{OfType: t}
}
arg := &schema.InputValue{
Name: schema.Ident{Text: "id"},
Type: t,
}
args = append(args, arg)
}
query.Fields = append(query.Fields, &schema.Field{
Name: sanitizeForGraphQLSchema(ti.Singular),
Type: outputTypeName,
Args: args,
})
query.Fields = append(query.Fields, &schema.Field{
Name: sanitizeForGraphQLSchema(pti.Plural),
Type: pluralOutputTypeName,
Args: args,
})
mutation.Fields = append(mutation.Fields, &schema.Field{
Name: sanitizeForGraphQLSchema(ti.Singular),
Args: append(args, schema.InputValueList{
&schema.InputValue{
Name: schema.Ident{Text: "insert"},
Type: inputTypeName,
},
&schema.InputValue{
Name: schema.Ident{Text: "inserts"},
Type: pluralInputTypeName,
},
&schema.InputValue{
Name: schema.Ident{Text: "update"},
Type: inputTypeName,
},
&schema.InputValue{
Name: schema.Ident{Text: "updates"},
Type: pluralInputTypeName,
},
}...),
Type: outputType,
})
}
err := engineSchema.ResolveTypes()
if err != nil {
return err
}
sg.Engine.Resolver = resolvers.Func(func(request *resolvers.ResolveRequest, next resolvers.Resolution) resolvers.Resolution {
resolver := resolvers.MetadataResolver.Resolve(request, next)
if resolver != nil {
return resolver
}
resolver = resolvers.MethodResolver.Resolve(request, next) // needed by the MetadataResolver
if resolver != nil {
return resolver
}
return nil
})
return nil
}