1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123
|
package main
import (
"encoding/json"
"fmt"
"io"
"log"
"mime"
"os"
"path/filepath"
"strings"
"git.sr.ht/~emersion/gqlclient"
"github.com/spf13/cobra"
)
var completeService = cobra.FixedCompletions(
[]string{"builds", "git", "hg", "lists", "meta", "pages", "paste", "todo"},
cobra.ShellCompDirectiveNoFileComp)
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)
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: completeService,
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", !isStdinTerminal, "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)
}
|