diff --git a/gen.go b/gen.go index 657aa845..0b490b66 100644 --- a/gen.go +++ b/gen.go @@ -30,9 +30,8 @@ const ( inputObjectFile string = "input.go" interfacesFile string = "interfaces.go" objectFile string = "object.go" - queryFile string = "query.go" - mutationFile string = "mutation.go" - payloadFile string = "payload.go" + // mutationFile string = "mutation.go" + payloadFile string = "payload.go" // scalarFile string = "scalar.go" // NOTE: probably not useful // unionFile string = "union.go" // NOTE: probably not useful ) @@ -207,12 +206,47 @@ func main() { } schema := graphql.MustParseSchema(graphqlSchema, nil, opts...) schemaAst := schema.ASTSchema() - genEnums(schemaAst.Enums) - err := run() - if err != nil { - log.Fatalln(err) + inputObjects := map[string]*types.InputObject{} + objects := map[string]*types.ObjectTypeDefinition{} + enums := map[string]*types.EnumTypeDefinition{} + interfaces := map[string]*types.InterfaceTypeDefinition{} + unions := map[string]*types.Union{} + scalars := map[string]*types.ScalarTypeDefinition{} + for name, graphqlType := range schemaAst.Types { + switch v := graphqlType.(type) { + case *types.EnumTypeDefinition: + enums[name] = v + case *types.InputObject: + inputObjects[name] = v + case *types.InterfaceTypeDefinition: + interfaces[name] = v + case *types.ObjectTypeDefinition: + objects[name] = v + case *types.ScalarTypeDefinition: + scalars[name] = v + case *types.Union: + unions[name] = v + default: + panic(fmt.Errorf("Unknown GraphQL type: %v", v)) + } } + genMutations(objects) + // genEnums(schemaAst.Enums) + + // err := run() + // if err != nil { + // log.Fatalln(err) + // } +} + +func sortedMapKeys[T any](schemaMap map[string]T) []string { + sortedNames := make([]string, 0, len(schemaMap)) + for k := range schemaMap { + sortedNames = append(sortedNames, k) + } + slices.Sort(sortedNames) + return sortedNames } func genEnums(schemaEnums []*types.EnumTypeDefinition) { @@ -237,6 +271,80 @@ func genEnums(schemaEnums []*types.EnumTypeDefinition) { } } +var queryRenames = map[string]string{ + "CustomActionsTriggerDefinitions": "TriggerDefinitions", +} + +func queryRename(name string) string { + if rename, ok := queryRenames[name]; ok { + return rename + } + return name +} + +func isObjectType(fieldDef *types.FieldDefinition) bool { + var unwrappedType types.Type + + if nonNull, ok := fieldDef.Type.(*types.NonNull); ok { + unwrappedType = nonNull.OfType + } else { + unwrappedType = fieldDef.Type + } + + return unwrappedType.Kind() == "OBJECT" +} + +var deleteInputMapping = map[string]string{ + "AlertSourceServiceDeleteInput": "ID", + "CategoryDeleteInput": "ID", + "CheckDeleteInput": "ID", + "DeleteInput": "ID", + "LevelDeleteInput": "ID", + "TagDeleteInput": "ID", + "ToolDeleteInput": "ID", + "TeamDeleteInput": "string", + "IdentifierInput": "string", +} + +func deleteInputRename(inputValue *types.InputValueDefinition) string { + inputType := strings.TrimSuffix(inputValue.Type.String(), "!") + if convertedValue, ok := deleteInputMapping[inputType]; ok { + return convertedValue + } + return inputType +} + +func doDebug(dbg any) string { + return "" +} + +func genMutations(objects map[string]*types.ObjectTypeDefinition) { + var buf bytes.Buffer + + buf.WriteString(header) + + tmpl := template.New("mutations") + tmpl.Funcs(sprig.TxtFuncMap()) + tmpl.Funcs(templFuncMap) + template.Must(tmpl.ParseFiles("./templates/mutations.tpl")) + + if err := tmpl.ExecuteTemplate(&buf, "create_operation", objects["Mutation"]); err != nil { + panic(err) + } + if err := tmpl.ExecuteTemplate(&buf, "update_operation", objects["Mutation"]); err != nil { + panic(err) + } + if err := tmpl.ExecuteTemplate(&buf, "delete_operation", objects["Mutation"]); err != nil { + panic(err) + } + + fmt.Println("writing mutation.go") + err := os.WriteFile("mutation.go", buf.Bytes(), 0o644) + if err != nil { + panic(err) + } +} + func getRootSchema() (*GraphQLSchema, error) { visibility, ok := os.LookupEnv("GRAPHQL_VISIBILITY") if !ok { @@ -294,14 +402,12 @@ func run() error { subSchema = inputObjectSchema case interfacesFile: subSchema = interfaceSchema - case objectFile: - subSchema = objectSchema - case mutationFile: - subSchema = objectSchema + // case objectFile: + // subSchema = objectSchema + // case mutationFile: + // subSchema = objectSchema case payloadFile: subSchema = objectSchema - case queryFile: - subSchema = objectSchema // case scalarFile: // subSchema = scalarSchema // case unionFile: @@ -481,203 +587,74 @@ type {{.Name}} struct { {{range .InputFields }} } {{- end }}{{ end -}} `), - // NOTE: "account" == objectSchema.Types[0] - // NOTE: "mutation" == objectSchema.Types[134] - queryFile: t(header + ` - import "fmt" - - {{range .Types | sortByName}} - {{if and (eq .Kind "OBJECT") (not (internal .Name)) }} - {{- if eq .Name "Account" }} - {{- template "account_queries" . }} - {{- else }} - {{- template "non_account_queries" . }} - {{- end}} - {{- end}} - {{- end}} - - {{ define "account_queries" -}} - {{- range .Fields }} {{- if and (len .Args) (not (skip_query .Name)) }} - // {{ if gt (len .Args) 3 -}} List {{- else -}} Get {{- end -}} - {{- .Name | title}} {{ .Description | clean | endSentence }} - func (client *Client) {{ if gt (len .Args) 3 }}List{{ .Name | title | makePlural }}(variables *PayloadVariables) (* - {{- if eq .Name "customActionsExternalActions" }}{{ .Name | title }}Connection, error) { - {{- else}}{{ .Name | title | makeSingular }}Connection, error) { - {{- end -}} - {{- else -}} Get{{ .Name | title }}(value string) (*{{.Name | title | trimSuffix "sVaultsSecret" }}, error) { - {{- end -}} - var q struct { - Account struct { - {{ if gt (len .Args) 3 -}} - {{- .Name | title | makePlural }} {{ if eq .Name "customActionsExternalActions" -}}{{ .Name | title }}{{ else }}{{ .Name | title | makeSingular }}{{ end }}Connection {{ template "graphql_struct_tag_with_args" . }} - {{- else -}} - {{- .Name | title }} {{ .Name | title | makeSingular | trimSuffix "sVaultsSecret" }} {{ template "graphql_struct_tag_with_args" . }} - {{- end -}} - } - } - {{- if gt (len .Args) 3 }} - if variables == nil { - variables = client.InitialPageVariablesPointer() - } - {{ else }} - v := PayloadVariables{ {{ range .Args }} - "{{.Name}}": value, {{ end}} - } - {{- end }} - - {{ if gt (len .Args) 3 -}} - if err := client.Query(&q, *variables, WithName("{{ template "name_to_singular" . }}List")); err != nil { - return nil, err - } - - for q.Account.{{ .Name | title }}.PageInfo.HasNextPage { - (*variables)["after"] = q.Account.{{ .Name | title }}.PageInfo.End - resp, err := client.List{{ .Name | title }}(variables) - if err != nil { - return nil, err - } - q.Account.{{ .Name | title }}.Nodes = append(q.Account.{{ .Name | title }}.Nodes, resp.Nodes...) - q.Account.{{ .Name | title }}.PageInfo = resp.PageInfo - q.Account.{{ .Name | title }}.TotalCount += resp.TotalCount - } - return &q.Account.{{ .Name | title }}, nil - {{ else }} - err := client.Query(&q, v, WithName("{{ template "name_to_singular" . }}{{ if isListType .Name }}List{{else}}Get{{end}}")) - return &q.Account.{{ .Name | title }}, HandleErrors(err, nil) - {{- end }} - } - {{end}}{{- end}}{{- end}} - - {{ define "non_account_queries" -}} - {{- range .Fields }} {{- if and (len .Args) (not (skip_query $.Name)) }} - // {{ if gt (len .Args) 3 }}List{{- else }}Get{{ end }}{{.Name | title}} {{ .Description | clean | endSentence }} - func ( {{- $.Name | first_char_lowered }} *{{ $.Name | title | makeSingular }}) - - {{- if gt (len .Args) 3 }}List{{ .Name | title }}(client *Client, variables *PayloadVariables) (* - {{- if or (hasPrefix "ancestor" .Name) (hasPrefix "child" .Name) }} {{- $.Name }}Connection, error - {{- else if hasPrefix "descendant" .Name }}{{ .Name | title | makeSingular | trimPrefix "Descendant" }}Connection, error - {{- else }}{{ if eq .Name "memberships" }}Team{{end}}{{ .Name | title | makeSingular | trimPrefix "Child" }}Connection, error - {{- end -}} ) { - if {{ $.Name | first_char_lowered }}.Id == "" { - return nil, fmt.Errorf("Unable to get {{ .Name | title }}, invalid {{ $.Name | lower }} id: '%s'", {{ $.Name | first_char_lowered }}.Id) - } - var q struct { - Account struct { - {{ $.Name | title | makeSingular }} struct { - {{- if or (hasPrefix "ancestor" .Name) (hasPrefix "child" .Name) -}} - {{ .Name | title }} {{ $.Name | title | makeSingular }}Connection - {{- else if hasPrefix "descendant" .Name }} - {{ .Name | title }} {{ .Name | title | makeSingular | trimPrefix "Descendant" }}Connection - {{- else -}} - {{ .Name | title }} {{ if eq .Name "memberships" }}Team{{end}}{{ .Name | title | makeSingular }}Connection - {{- end }} ` + "`" + `graphql:"{{.Name}}(after: $after, first: $first)"` + "`" + ` - } ` + "`" + `graphql:"{{$.Name | word_first_char_lowered }}(id: $id)"` + "`" + ` - } - } - if variables == nil { - variables = client.InitialPageVariablesPointer() - } - (*variables)["id"] = {{ $.Name | first_char_lowered }}.Id - if err := client.Query(&q, *variables, WithName("{{ template "name_to_singular" . }}List")); err != nil { - return nil, err - } - - for q.Account.{{ $.Name | title | makeSingular }}.{{ .Name | title }}.PageInfo.HasNextPage { - (*variables)["after"] = q.Account.{{ $.Name | title | makeSingular }}.{{ .Name | title }}.PageInfo.End - connection, err := {{ $.Name | first_char_lowered }}.List{{ .Name | title }}(client, variables) - if err != nil { - return nil, err - } - q.Account.{{ $.Name | title | makeSingular }}.{{ .Name | title }}.Nodes = append(q.Account.{{ $.Name | title | makeSingular }}.{{ .Name | title }}.Nodes, connection.Nodes...) - q.Account.{{ $.Name | title | makeSingular }}.{{ .Name | title }}.PageInfo = q.Account.{{ $.Name | title | makeSingular }}.{{ .Name | title }}.PageInfo - q.Account.{{ $.Name | title | makeSingular }}.{{ .Name | title }}.TotalCount += q.Account.{{ $.Name | title | makeSingular }}.{{ .Name | title }}.TotalCount - } - - return &q.Account.{{ $.Name | title | makeSingular }}.{{ .Name | title }}, nil - - {{- else }}Get{{ .Name | title }}({{ query_args . }}) (*{{.Name | title | makeSingular }}, error) { - var q struct { - Account struct { - {{ .Name | title }} {{ template "name_to_singular" . }} ` + "`" + `graphql:"{{.Name}}(input: $input)"` + "`" + ` - } - } - v := PayloadVariables{"input": *NewIdentifier(identifier)} - if err := client.Query(&q, v, WithName("{{ template "name_to_singular" . }}Get")); err != nil { - return nil, err - } - return &q.Account.{{ .Name | title }}, nil - {{- end -}} - } - {{- end -}}{{- end -}}{{- end -}} - `), - mutationFile: t(header + ` - {{range .Types | sortByName}} - {{if and (eq .Kind "OBJECT") (not (internal .Name)) }} - {{- if eq .Name "Mutation" }} - {{- template "mutation" .}} - {{end}} - {{- end}} - {{- end}} - - {{ define "mutation" -}} - {{- range .Fields }} {{- if not (skip_if_campaign_or_group .Name) }} - // {{ .Name | title | renameMutation }} {{ .Description | clean | fullSentence }} - func (client *Client) {{ .Name | title | renameMutation }}( - {{- if hasSuffix "Delete" .Name }}id ID - {{- else }} - {{- range $index, $element := .Args }} {{- if gt $index 0 }}, {{ end -}} - {{- if eq "IdentifierInput" .Type.OfType.OfTypeName }}identifier string - {{- else if hasSuffix "Delete" $.Name }}id ID - {{- else if eq "String" .Type.OfType.OfTypeName }}{{ .Name }} string - {{- else }}{{- .Name }} {{ with .Type.OfType.OfTypeName }}{{.}}{{else}}any{{end}} - {{- end }} - {{- end }} - {{- end -}} ) {{ if hasSuffix "Delete" .Name -}} - error { - {{- else -}} - (*{{.Name | title | renameMutationReturnType}}, error) { - {{- end -}} - {{- if hasSuffix "Delete" .Name }} - input := {{.Name | title}}Input{Id: id} - {{ end }} - var m struct { - {{ .Name | title }}Payload {{ template "graphql_struct_tag_with_args" . }} - } - v := PayloadVariables{ {{ range .Args }} - "{{.Name}}": {{- if eq "IdentifierInput" .Type.OfType.OfTypeName }}*NewIdentifier(identifier), - {{- else}}input,{{ end }} - {{- end}} - } - err := client.Mutate(&m, v, WithName("{{ .Name | title }}")) - {{- if hasSuffix "Delete" .Name }} - return HandleErrors(err, m.{{ .Name | title }}Payload.Errors) - {{- else }} - return &m.{{ .Name | title }}Payload.{{ .Name | title | renameMutationReturnType}}, HandleErrors(err, m.{{ .Name | title }}Payload.Errors) - {{- end }} - } - {{- end}}{{ end }}{{- end}} - `), - objectFile: t(header + ` - import "github.com/relvacode/iso8601" - - {{range .Types | sortByName}} - {{if and (eq .Kind "OBJECT") (not (internal .Name)) }} - {{- if ne .Name "Account" }} - {{template "object" .}}{{end}} - {{- end}} - {{- end}} - - {{- define "object" -}} - {{ if not (skip_object .Name) }} - {{ template "type_comment_description" . }} - type {{.Name}} struct { {{ add_special_fields .Name }} - {{ range .Fields }} - {{- if and (not (skip_object_field $.Name .Name)) (not (len .Args)) }} - {{ .Name | title}} {{ get_field_type $.Name . }} {{ template "graphql_struct_tag" . }} {{ template "field_comment_description" . }} - {{- end -}}{{ end }} - } - {{- end }}{{- end -}} - `), + // mutationFile: t(header + ` + // {{range .Types | sortByName}} + // {{if and (eq .Kind "OBJECT") (not (internal .Name)) }} + // {{- if eq .Name "Mutation" }} + // {{- template "mutation" .}} + // {{end}} + // {{- end}} + // {{- end}} + + // {{ define "mutation" -}} + // {{- range .Fields }} {{- if not (skip_if_campaign_or_group .Name) }} + // // {{ .Name | title | renameMutation }} {{ .Description | clean | fullSentence }} + // func (client *Client) {{ .Name | title | renameMutation }}( + // {{- if hasSuffix "Delete" .Name }}id ID + // {{- else }} + // {{- range $index, $element := .Args }} {{- if gt $index 0 }}, {{ end -}} + // {{- if eq "IdentifierInput" .Type.OfType.OfTypeName }}identifier string + // {{- else if hasSuffix "Delete" $.Name }}id ID + // {{- else if eq "String" .Type.OfType.OfTypeName }}{{ .Name }} string + // {{- else }}{{- .Name }} {{ with .Type.OfType.OfTypeName }}{{.}}{{else}}any{{end}} + // {{- end }} + // {{- end }} + // {{- end -}} ) {{ if hasSuffix "Delete" .Name -}} + // error { + // {{- else -}} + // (*{{.Name | title | renameMutationReturnType}}, error) { + // {{- end -}} + // {{- if hasSuffix "Delete" .Name }} + // input := {{.Name | title}}Input{Id: id} + // {{ end }} + // var m struct { + // {{ .Name | title }}Payload {{ template "graphql_struct_tag_with_args" . }} + // } + // v := PayloadVariables{ {{ range .Args }} + // "{{.Name}}": {{- if eq "IdentifierInput" .Type.OfType.OfTypeName }}*NewIdentifier(identifier), + // {{- else}}input,{{ end }} + // {{- end}} + // } + // err := client.Mutate(&m, v, WithName("{{ .Name | title }}")) + // {{- if hasSuffix "Delete" .Name }} + // return HandleErrors(err, m.{{ .Name | title }}Payload.Errors) + // {{- else }} + // return &m.{{ .Name | title }}Payload.{{ .Name | title | renameMutationReturnType}}, HandleErrors(err, m.{{ .Name | title }}Payload.Errors) + // {{- end }} + // } + // {{- end}}{{ end }}{{- end}} + // `), + // objectFile: t(header + ` + // import "github.com/relvacode/iso8601" + + // {{range .Types | sortByName}} + // {{if and (eq .Kind "OBJECT") (not (internal .Name)) }} + // {{- if ne .Name "Account" }} + // {{template "object" .}}{{end}} + // {{- end}} + // {{- end}} + + // {{- define "object" -}} + // {{ if not (skip_object .Name) }} + // {{ template "type_comment_description" . }} + // type {{.Name}} struct { {{ add_special_fields .Name }} + // {{ range .Fields }} + // {{- if and (not (skip_object_field $.Name .Name)) (not (len .Args)) }} + // {{ .Name | title}} {{ get_field_type $.Name . }} {{ template "graphql_struct_tag" . }} {{ template "field_comment_description" . }} + // {{- end -}}{{ end }} + // } + // {{- end }}{{- end -}} + // `), // scalarFile: t(header + ` // import ( // "encoding/base64" @@ -959,12 +936,13 @@ func firstCharLowered(s string) string { var templFuncMap = template.FuncMap{ "internal": func(s string) bool { return strings.HasPrefix(s, "__") }, + "queryRename": queryRename, "quote": strconv.Quote, - "join": strings.Join, + "doDebug": doDebug, + "deleteInputRename": deleteInputRename, "check_fragments": fragmentsForCheck, "custom_actions_ext_action_fragments": fragmentsForCustomActionsExtAction, "integration_fragments": fragmentsForIntegration, - "get_field_type": getFieldType, "get_input_field_type": getInputFieldType, "add_special_fields": addSpecialFields, "add_special_interfaces_fields": addSpecialInterfacesFields, @@ -975,6 +953,7 @@ var templFuncMap = template.FuncMap{ "skip_query": skipQuery, "skip_interface_field": skipInterfaceField, "example_tag_value": getExampleValue, + "isObjectType": isObjectType, "isListType": isPlural, "renameMutation": renameMutation, "renameMutationReturnType": renameMutationReturnType, @@ -1190,190 +1169,6 @@ func getInputFieldType(inputField GraphQLField) string { return "string" } -func getFieldType(objectName string, inputField GraphQLField) string { - lowercaseFieldName := strings.ToLower(inputField.Name) - switch { - case "type" == lowercaseFieldName: - switch objectName { - case "AlertSource": - return "AlertSourceTypeEnum" - case "AlertSourceUsageCheck", "CustomCheck", "CustomEventCheck", - "GitBranchProtectionCheck", "HasDocumentationCheck", "HasRecentDeployCheck", - "ManualCheck", "PayloadCheck", "RepositoryFileCheck", "RepositoryGrepCheck", - "RepositoryIntegratedCheck", "RepositorySearchCheck", "ServiceConfigurationCheck", - "ServiceDependencyCheck", "ServiceOwnershipCheck", "ServicePropertyCheck", - "TagDefinedCheck", "ToolUsageCheck": - return "CheckType" - case "ApiDocIntegration", "AwsIntegration", "AzureDevopsIntegration", - "AzureDevopsPermissionError", "BitbucketIntegration", "CheckIntegration", - "DatadogIntegration", "DeployIntegration", "FluxIntegration", "GenericIntegration", - "GithubActionsIntegration", "GithubIntegration", "GitlabIntegration", - "InfrastructureResource", "InfrastructureResourceSchema", "Repository", - "IssueTrackingIntegration", "JenkinsIntegration", "KubernetesIntegration", - "NewRelicIntegration", "OctopusDeployIntegration", "OnPremGitlabIntegration", - "OpsgenieIntegration", "PagerdutyIntegration", "PayloadIntegration", - "RelationshipType", "ScimIntegration", "SlackIntegration", "TerraformIntegration": - return "string" - case "Contact": - return "ContactType" - case "FilterPredicate": - return "PredicateTypeEnum" - case "InfrastructureResourceProviderData": - return "DoubleCheckThis" - case "Predicate": - return "PredicateTypeEnum" - default: - return "any" - } - case objectName == "AlertSource" && lowercaseFieldName == "integration": - return "IntegrationId" - case objectName == "AlertSourceService": - switch lowercaseFieldName { - case "alertsource": - return "AlertSource" - case "service": - return "ServiceId" - case "status": - return "AlertSourceStatusTypeEnum" - } - case objectName == "CustomActionsTriggerDefinition": - switch lowercaseFieldName { - case "accesscontrol": - return "CustomActionsTriggerDefinitionAccessControlEnum" - case "action": - return "CustomActionsId" - case "entitytype": - return "CustomActionsEntityTypeEnum" - case "filter": - return "FilterId" - case "owner": - return "TeamId" - } - case objectName == "CustomActionsWebhookAction": - switch lowercaseFieldName { - case "headers": - return "JSON" - case "httpmethod": - return "CustomActionsHttpMethodEnum" - } - case objectName == "Domain": - switch lowercaseFieldName { - case "managedaliases": - return "[]string" - case "owner": - return "EntityOwner" - } - case objectName == "Filter": - switch lowercaseFieldName { - case "connective": - return "ConnectiveEnum" - case "predicates": - return "[]FilterPredicate" - } - case objectName == "FilterPredicate": - switch lowercaseFieldName { - case "casesensitive": - return "*bool" - case "key": - return "PredicateKeyEnum" - } - case objectName == "InfrastructureResource": - switch lowercaseFieldName { - case "data", "rawdata": - return "JSON" - case "id": - return "ID" - case "owner": - return "EntityOwner" - case "providerdata": - return "InfrastructureResourceProviderData" - } - case objectName == "InfrastructureResourceSchema" && lowercaseFieldName == "schema": - return "JSON" - case objectName == "Language" && lowercaseFieldName == "usage": - return "float64" - case objectName == "Repository": - switch lowercaseFieldName { - case "languages": - return "[]Language" - case "owner": - return "TeamId" - } - case objectName == "Scorecard": - switch lowercaseFieldName { - case "owner": - return "EntityOwner" - case "passingchecks", "servicecount", "totalchecks": - return "int" - } - case objectName == "Secret" && lowercaseFieldName == "owner": - return "TeamId" - case objectName == "Repository" && lowercaseFieldName == "owner": - return "TeamId" - case objectName == "Service": - switch lowercaseFieldName { - case "managedaliases": - return "[]string" - case "owner": - return "TeamId" - case "preferredapidocument": - return "*ServiceDocument" - case "preferredapidocumentsource": - return "*ApiDocumentSourceEnum" - } - case objectName == "ServiceDependency": - switch lowercaseFieldName { - case "destinationservice", "sourceservice": - return "ServiceId" - } - case objectName == "ServiceDocument" && lowercaseFieldName == "source": - return "ServiceDocumentSource" - case objectName == "ServiceRepository": - switch lowercaseFieldName { - case "repository": - return "RepositoryId" - case "service": - return "ServiceId" - } - case objectName == "System": - switch lowercaseFieldName { - case "managedaliases": - return "[]string" - case "owner": - return "EntityOwner" - case "parent": - return "Domain" - } - case objectName == "Team": - switch lowercaseFieldName { - case "contacts": - return "Contact" - case "managedaliases": - return "[]string" - case "parentteam": - return "TeamId" - } - case objectName == "TeamMembership": - switch lowercaseFieldName { - case "team": - return "TeamId" - case "user": - return "UserId" - } - case objectName == "Tool": - switch lowercaseFieldName { - case "category": - return "ToolCategory" - case "service": - return "ServiceId" - } - case objectName == "User" && lowercaseFieldName == "role": - return "UserRole" - } - - return getInputFieldType(inputField) -} - func getExampleValueByFieldName(inputField GraphQLInputValue) string { mapFieldTypeToExampleValue := map[string]string{ "DocumentSubtype": "openapi", diff --git a/go.mod b/go.mod index 810ec71f..88f6843a 100644 --- a/go.mod +++ b/go.mod @@ -27,6 +27,7 @@ require ( github.com/go-playground/universal-translator v0.18.1 // indirect github.com/google/uuid v1.6.0 // indirect github.com/gosimple/unidecode v1.0.1 // indirect + github.com/graph-gophers/graphql-go v1.5.0 // indirect github.com/hashicorp/go-cleanhttp v0.5.2 // indirect github.com/huandu/xstrings v1.5.0 // indirect github.com/leodido/go-urn v1.4.0 // indirect diff --git a/go.sum b/go.sum index 57a7a373..4dc4887d 100644 --- a/go.sum +++ b/go.sum @@ -9,6 +9,7 @@ github.com/Masterminds/sprig/v3 v3.3.0/go.mod h1:Zy1iXRYNqNLUolqCpL4uhk6SHUMAOSC github.com/coder/websocket v1.8.12 h1:5bUXkEPPIbewrnkU8LTCLVaxi4N4J8ahufH2vlo4NAo= github.com/coder/websocket v1.8.12/go.mod h1:LNVeNrXQZfe5qhS9ALED3uA+l5pPqvwXg3CKoDBB2gs= github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= @@ -17,6 +18,9 @@ github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHk github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0= github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk= +github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s= github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= @@ -28,6 +32,7 @@ github.com/go-playground/validator/v10 v10.23.0/go.mod h1:dbuPbCMFw/DrkbEynArYaC github.com/go-resty/resty/v2 v2.16.2 h1:CpRqTjIzq/rweXUt9+GxzzQdlkqMdt8Lm/fuK/CAbAg= github.com/go-resty/resty/v2 v2.16.2/go.mod h1:0fHAoK7JoBy/Ch36N8VFeMsK7xQOHhvWaC3iOktwmIU= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= +github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= @@ -36,6 +41,8 @@ github.com/gosimple/slug v1.15.0 h1:wRZHsRrRcs6b0XnxMUBM6WK1U1Vg5B0R7VkIf1Xzobo= github.com/gosimple/slug v1.15.0/go.mod h1:UiRaFH+GEilHstLUmcBgWcI42viBN7mAb818JrYOeFQ= github.com/gosimple/unidecode v1.0.1 h1:hZzFTMMqSswvf0LBJZCZgThIZrpDHFXux9KeGmn6T/o= github.com/gosimple/unidecode v1.0.1/go.mod h1:CP0Cr1Y1kogOtx0bJblKzsVWrqYaqfNOnHzpgWw4Awc= +github.com/graph-gophers/graphql-go v1.5.0 h1:fDqblo50TEpD0LY7RXk/LFVYEVqo3+tXMNMPSVXA1yc= +github.com/graph-gophers/graphql-go v1.5.0/go.mod h1:YtmJZDLbF1YYNrlNAuiO5zAStUWc3XZT07iGsVqe1Os= github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ= github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= github.com/hashicorp/go-hclog v1.6.3 h1:Qr2kF+eVWjTiYmU7Y31tYlP1h0q/X3Nl3tPGdaB11/k= @@ -64,6 +71,7 @@ github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyua github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= +github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc= github.com/opslevel/moredefaults v0.0.0-20240112142637-078c8ff8ba9c h1:m4sNHcfkE02xZy1oxF2QVGfhHulamxw9UlzRM7c45QQ= github.com/opslevel/moredefaults v0.0.0-20240112142637-078c8ff8ba9c/go.mod h1:g2GSXVP6LO+5+AIsnMRPN+BeV86OXuFRTX7HXCDtYeI= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= @@ -83,8 +91,13 @@ github.com/shopspring/decimal v1.4.0 h1:bxl37RwXBklmTi0C79JfXCEBD1cqqHt0bbgBAGFp github.com/shopspring/decimal v1.4.0/go.mod h1:gawqmDU56v4yIKSwfBSFip1HdCCXN8/+DMd9qYNcwME= github.com/spf13/cast v1.7.0 h1:ntdiHjuueXFgm5nzDRdOS4yfT43P5Fnud6DH50rz/7w= github.com/spf13/cast v1.7.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +go.opentelemetry.io/otel v1.6.3/go.mod h1:7BgNga5fNlF/iZjG06hM3yofffp0ofKCDwSXx1GC4dI= +go.opentelemetry.io/otel/trace v1.6.3/go.mod h1:GNJQusJlUgZl9/TQBPKU/Y/ty+0iVB5fjhKeJGZPGFs= golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U= golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys= @@ -98,6 +111,8 @@ golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo= golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= golang.org/x/time v0.6.0 h1:eTDhh4ZXt5Qf0augr54TN6suAUudPcawVZeIAPU7D4U= golang.org/x/time v0.6.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/templates/mutations.tpl b/templates/mutations.tpl new file mode 100644 index 00000000..32b9a153 --- /dev/null +++ b/templates/mutations.tpl @@ -0,0 +1,71 @@ +{{ define "create_operation" -}} +{{- end }} + +{{ define "update_operation" -}} +{{- end }} + +{{ define "delete_operation" -}} + {{- range .Fields }} + {{- if hasSuffix "Delete" .Name }} +// {{ title $.Name }} {{ .Desc | replace "\n" " " | endSentence }} +func (client *Client) Delete{{ title .Name | trimSuffix "Delete" }}( {{- template "delete_input_args" . -}} ) error { + var d struct { + Payload struct { + Errors []OpsLevelErrors `graphql:"errors"` + } `graphql:"{{ .Name }}( {{- template "graphql_delete_input_args" . -}} )"` + } + v := PayloadVariables{ + {{ template "delete_payload_variables" . }} + } + err := client.Mutate(&d, v, WithName("{{ title .Name }}")) + return HandleErrors(err, d.Payload.Errors) +} + {{- end }} + {{- end }} +{{- end }} + +{{ define "delete_payload_variables" }} + {{- range $index, $arg := .Arguments -}} + {{- if hasPrefix "IdentifierInput" .Type.String -}} + "{{.Name.Name}}": identifier, {{- nindent 4 "" -}} + {{- else if contains (trimSuffix "!" .Type.String) (list "ContactDeleteInput" "DeleteInput" | join " " ) -}} + "{{.Name.Name}}": {{ trimSuffix "!" .Type.String }}{ {{- nindent 4 "" -}} + Id: id, {{- nindent 4 "" -}} + {{- nindent 4 "}," -}} + {{- else if contains (trimSuffix "!" .Type.String) (list "AliasDeleteInput" "String" | join " " ) -}} + "{{.Name.Name}}": {{.Name.Name}}, {{- nindent 4 "" -}} + {{- else -}} + "{{.Name.Name}}": {{ trimSuffix "!" .Type.String }}{ {{- nindent 4 "" -}} + {{- with deleteInputRename $arg -}} + {{- if eq . "ID" -}} + Id: id, + {{- else -}} + {{ $arg.Name.Name }}: {{ . }}, + {{ end -}} + {{- end -}} + {{- nindent 4 "}," -}} + {{- end -}} + {{- end -}} +{{- end }} + +{{ define "delete_input_args" }} + {{- range $index, $arg := .Arguments -}} {{- if gt $index 0 }}, {{ end -}} + {{- with deleteInputRename $arg -}} + {{- if eq . "ID" -}} + id ID + {{- else if eq . "String" -}} + {{ $arg.Name.Name }} string + {{- else if eq . "string" -}} + identifier string + {{- else -}} + {{ $arg.Name.Name }} {{ . }} + {{- end -}} + {{- end -}} + {{- end -}} +{{- end }} + +{{ define "graphql_delete_input_args" }} + {{- range $index, $arg := .Arguments -}} {{- if gt $index 0 }}, {{ end -}} + {{ $arg.Name.Name }}: ${{ $arg.Name.Name }} + {{- end -}} +{{- end }}