package admin_api import ( "fmt" "net/http" "git.ohea.xyz/cursorius/server/database" "github.com/google/uuid" "github.com/graphql-go/graphql" "github.com/graphql-go/handler" ) func createSchema(db database.Database) (graphql.Schema, error) { webhookType := graphql.NewObject(graphql.ObjectConfig{ Name: "Webhook", Description: "A webhook for triggering pipelines", Fields: graphql.Fields{ "id": &graphql.Field{ Type: graphql.NewNonNull(graphql.String), Description: "The id of the webhook.", Resolve: func(p graphql.ResolveParams) (interface{}, error) { if webhook, ok := p.Source.(database.Webhook); ok { return webhook.Id, nil } return nil, nil }, }, "serverType": &graphql.Field{ Type: graphql.NewNonNull(graphql.String), Description: "The format of the webhook.", Resolve: func(p graphql.ResolveParams) (interface{}, error) { if webhook, ok := p.Source.(database.Webhook); ok { return webhook.ServerType, nil } return nil, nil }, }, "secret": &graphql.Field{ Type: graphql.NewNonNull(graphql.String), Description: "The secret used to validate the webhook.", Resolve: func(p graphql.ResolveParams) (interface{}, error) { if webhook, ok := p.Source.(database.Webhook); ok { return webhook.Secret, nil } return nil, nil }, }, }, }) pipelineType := graphql.NewObject(graphql.ObjectConfig{ Name: "Pipeline", Description: "A pipeline for running ci jobs", Fields: graphql.Fields{ "id": &graphql.Field{ Type: graphql.NewNonNull(graphql.String), Description: "The id of the pipeline.", Resolve: func(p graphql.ResolveParams) (interface{}, error) { if pipeline, ok := p.Source.(database.Pipeline); ok { return pipeline.Id, nil } return nil, nil }, }, "name": &graphql.Field{ Type: graphql.NewNonNull(graphql.String), Description: "The name of the pipeline.", Resolve: func(p graphql.ResolveParams) (interface{}, error) { if pipeline, ok := p.Source.(database.Pipeline); ok { return pipeline.Name, nil } return nil, nil }, }, "url": &graphql.Field{ Type: graphql.NewNonNull(graphql.String), Description: "The url of the pipeline.", Resolve: func(p graphql.ResolveParams) (interface{}, error) { if pipeline, ok := p.Source.(database.Pipeline); ok { return pipeline.Url, nil } return nil, nil }, }, "pollInterval": &graphql.Field{ Type: graphql.NewNonNull(graphql.Int), Description: "The polling interval for the pipeline.", Resolve: func(p graphql.ResolveParams) (interface{}, error) { if pipeline, ok := p.Source.(database.Pipeline); ok { return pipeline.PollInterval, nil } return nil, nil }, }, "createWebhook": &graphql.Field{ Type: webhookType, Description: "Create a new webhook", Args: graphql.FieldConfigArgument{ "type": &graphql.ArgumentConfig{ Type: graphql.NewNonNull(graphql.String), }, }, Resolve: func(params graphql.ResolveParams) (interface{}, error) { webhook, err := db.CreateWebhook( database.WebhookSender(params.Args["type"].(string)), params.Source.(database.Pipeline).Id, ) if err != nil { return nil, err } return webhook, nil }, }, "webhooks": &graphql.Field{ Type: graphql.NewNonNull(graphql.NewList(graphql.NewNonNull(webhookType))), Description: "The list of webhooks for the pipeline.", Resolve: func(p graphql.ResolveParams) (interface{}, error) { if pipeline, ok := p.Source.(database.Pipeline); ok { return db.GetWebhooksForPipeline(pipeline.Id) } return []database.Webhook{}, nil }, }, }, }) queryType := graphql.NewObject(graphql.ObjectConfig{ Name: "Query", Fields: graphql.Fields{ "Pipeline": &graphql.Field{ Type: pipelineType, Args: graphql.FieldConfigArgument{ "id": &graphql.ArgumentConfig{ Type: graphql.NewNonNull(graphql.String), Description: "The id of the requested pipeline.", }, }, Resolve: func(p graphql.ResolveParams) (interface{}, error) { id, err := uuid.Parse(p.Args["id"].(string)) if err != nil { return nil, err } return db.GetPipelineById(id) }, }, }, }) mutationType := graphql.NewObject(graphql.ObjectConfig{ Name: "Mutation", Fields: graphql.Fields{ "createPipeline": &graphql.Field{ Type: pipelineType, Description: "Create a new pipeline", Args: graphql.FieldConfigArgument{ "name": &graphql.ArgumentConfig{ Type: graphql.NewNonNull(graphql.String), }, "url": &graphql.ArgumentConfig{ Type: graphql.NewNonNull(graphql.String), }, "pollInterval": &graphql.ArgumentConfig{ Type: graphql.Int, }, }, Resolve: func(params graphql.ResolveParams) (interface{}, error) { var interval int if intervalVal, ok := params.Args["pollInterval"]; ok { interval = intervalVal.(int) } else { interval = 0 } pipeline, err := db.CreatePipeline( params.Args["name"].(string), params.Args["url"].(string), interval, ) if err != nil { return nil, err } return pipeline, nil }, }, }, }) schema, err := graphql.NewSchema(graphql.SchemaConfig{ Query: queryType, Mutation: mutationType, }) if err != nil { return schema, fmt.Errorf("Could not create schema: %w", err) } return schema, nil } func CreateHandler(db database.Database, mux *http.ServeMux) error { schema, err := createSchema(db) if err != nil { return err } h := handler.New(&handler.Config{ Schema: &schema, Pretty: true, GraphiQL: true, }) mux.Handle("/graphql", h) return nil }