package main import ( "encoding/json" "fmt" "io" "log" "mime" "os" "path/filepath" "strings" "git.sr.ht/~emersion/gqlclient" "git.sr.ht/~xenrox/hut/termfmt" "github.com/spf13/cobra") const graphqlPrefill = `# Please write the GraphQL query you want to execute above. The GraphQL schema# for %v.sr.ht is available at:# %v` func newGraphqlCommand() *cobra.Command { var stringVars, fileVars []string var stdin bool run := func(cmd *cobra.Command, args []string) { service := args[0] ctx := cmd.Context() c := createClient(service, cmd) // Disable $EDITOR support when not in interactive terminal if !termfmt.IsTerminal() { stdin = true } var query string if stdin { b, err := io.ReadAll(os.Stdin) if err != nil { log.Fatalf("failed to read GraphQL query: %v", err) } query = string(b) } else { prefill := fmt.Sprintf(graphqlPrefill, service, graphqlSchemaURL(service)) var err error query, err = getInputWithEditor("hut_query*.graphql", prefill) if err != nil { log.Fatalf("failed to read GraphQL query: %v", err) } query = dropComment(query, prefill) } if strings.TrimSpace(query) == "" { fmt.Fprintln(os.Stderr, "Aborting due to empty query") os.Exit(1) } op := gqlclient.NewOperation(query) for _, kv := range stringVars { op.Var(splitKeyValue(kv)) } for _, kv := range fileVars { k, filename := splitKeyValue(kv) f, err := os.Open(filename) if err != nil { log.Fatalf("in variable definition %q: %v", kv, err) } defer f.Close() op.Var(k, gqlclient.Upload{ Filename: filepath.Base(filename), MIMEType: mime.TypeByExtension(filename), Body: f, }) } var data json.RawMessage if err := c.Execute(ctx, op, &data); err != nil { log.Fatal(err) } enc := json.NewEncoder(os.Stdout) enc.SetIndent("", " ") if err := enc.Encode(data); err != nil { log.Fatalf("failed to write JSON response: %v", err) } } cmd := &cobra.Command{ Use: "graphql <service>", Short: "Execute a GraphQL query", Args: cobra.ExactArgs(1), ValidArgsFunction: cobra.NoFileCompletions, Run: run, } cmd.Flags().StringSliceVarP(&stringVars, "var", "v", nil, "set string variable") cmd.Flags().StringSliceVar(&fileVars, "file", nil, "set file variable") cmd.Flags().BoolVar(&stdin, "stdin", false, "read query from stdin") // TODO: JSON variable return cmd} func splitKeyValue(kv string) (string, string) { parts := strings.SplitN(kv, "=", 2) if len(parts) != 2 { log.Fatalf("in variable definition %q: missing equal sign", kv) } return parts[0], parts[1]} func graphqlSchemaURL(service string) string { var filename string switch service { case "pages": filename = "graph/schema.graphqls" default: filename = "api/graph/schema.graphqls" } return fmt.Sprintf("https://git.sr.ht/~sircmpwn/%v.sr.ht/tree/master/item/%v", service, filename)}
package main
import (
"encoding/json"
"fmt"
"io"
"log"
"mime"
"os"
"path/filepath"
"strings"
"git.sr.ht/~emersion/gqlclient"
"git.sr.ht/~xenrox/hut/termfmt"
"github.com/spf13/cobra"
)
const graphqlPrefill = `
# Please write the GraphQL query you want to execute above. The GraphQL schema
# for %v.sr.ht is available at:
# %v`
func newGraphqlCommand() *cobra.Command {
var stringVars, fileVars []string
var stdin bool
run := func(cmd *cobra.Command, args []string) {
service := args[0]
ctx := cmd.Context()
c := createClient(service, cmd)
// Disable $EDITOR support when not in interactive terminal
if !termfmt.IsTerminal() {
stdin = true
}
var query string
if stdin {
b, err := io.ReadAll(os.Stdin)
if err != nil {
log.Fatalf("failed to read GraphQL query: %v", err)
}
query = string(b)
} else {
prefill := fmt.Sprintf(graphqlPrefill, service, graphqlSchemaURL(service))
var err error
query, err = getInputWithEditor("hut_query*.graphql", prefill)
if err != nil {
log.Fatalf("failed to read GraphQL query: %v", err)
}
query = dropComment(query, prefill)
}
if strings.TrimSpace(query) == "" {
fmt.Fprintln(os.Stderr, "Aborting due to empty query")
os.Exit(1)
}
op := gqlclient.NewOperation(query)
for _, kv := range stringVars {
op.Var(splitKeyValue(kv))
}
for _, kv := range fileVars {
k, filename := splitKeyValue(kv)
f, err := os.Open(filename)
if err != nil {
log.Fatalf("in variable definition %q: %v", kv, err)
}
defer f.Close()
op.Var(k, gqlclient.Upload{
Filename: filepath.Base(filename),
MIMEType: mime.TypeByExtension(filename),
Body: f,
})
}
var data json.RawMessage
if err := c.Execute(ctx, op, &data); err != nil {
log.Fatal(err)
}
enc := json.NewEncoder(os.Stdout)
enc.SetIndent("", " ")
if err := enc.Encode(data); err != nil {
log.Fatalf("failed to write JSON response: %v", err)
}
}
cmd := &cobra.Command{
Use: "graphql <service>",
Short: "Execute a GraphQL query",
Args: cobra.ExactArgs(1),
ValidArgsFunction: cobra.NoFileCompletions,
Run: run,
}
cmd.Flags().StringSliceVarP(&stringVars, "var", "v", nil, "set string variable")
cmd.Flags().StringSliceVar(&fileVars, "file", nil, "set file variable")
cmd.Flags().BoolVar(&stdin, "stdin", false, "read query from stdin")
// TODO: JSON variable
return cmd
}
func splitKeyValue(kv string) (string, string) {
parts := strings.SplitN(kv, "=", 2)
if len(parts) != 2 {
log.Fatalf("in variable definition %q: missing equal sign", kv)
}
return parts[0], parts[1]
}
func graphqlSchemaURL(service string) string {
var filename string
switch service {
case "pages":
filename = "graph/schema.graphqls"
default:
filename = "api/graph/schema.graphqls"
}
return fmt.Sprintf("https://git.sr.ht/~sircmpwn/%v.sr.ht/tree/master/item/%v", service, filename)
}