175 lines
4.5 KiB
Go
175 lines
4.5 KiB
Go
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
|
|
}
|