Vincit / venia

Clojure(Script) graphql query generation
Eclipse Public License 1.0
197 stars 20 forks source link

Support JSON->graphql? #17

Closed nrakochy closed 7 years ago

nrakochy commented 7 years ago

Hi there.

Thanks for the library. I am working on a server-side endpoint and was attempting to use venia to coerce an incoming json request to a graphql query. Is this feasible?

Unfortunately I could not get this to work, as venia is specced out to use keywords rather than strings-

;; REPL 
(use '[clojure.data.json :as json])

;; from the example 
(def a [[:employee {:id 1 :active true} [:name :address [:friends [:name :email]]]]])

(def b (json/write-str a))
;;=> "[[\"employee\",{\"id\":1,\"active\":true},[\"name\",\"address\",
          [\"friends\",[\"name\",\"email\"]]]]]"

(def c (json/read-str b :key-fn keyword)
 ;;=> [["employee" {:id 1, :active true} ["name" "address" ["friends" ["name" "email"]]]]]
 (v/graphql-query {:venia/queries c})

ExceptionInfo Invalid query data  clojure.core/ex-info (core.clj:4725)
In: [:venia/queries 0 0] val: "employee" 
    fails spec: :venia/query-name at: [:venia/queries :query/data :query] predicate: keyword?
In: [:venia/queries 0] val: ["employee" {:id 1, :active true} ["name" "address" ["friends" ["name" "email"]]]] 
    fails spec: :venia/query at: [:venia/queries :venia/query-with-data] predicate: map?
:clojure.spec.alpha/spec  :venia/query-def
:clojure.spec.alpha/value  
#:venia{:queries [["employee" {:id 1, :active true} ["name" "address" ["friends" ["name" "email"]]]]]}

Since calling (keyword :example-key) just returns the key, I tried updating spec & core with something like this to coerce the incoming string

(defn arg->name [x]
   (name (keyword x))

but to no avail. What changes might be needed to support a generic JSONified string (e.g. (def b) above)?

decoursin commented 7 years ago

Sorry, why can't you just turn all strings into keywords? Something like this (untested):

(def c (clojure.walk/postwalk (fn [x] (if (string? x) (keyword x) x))) (json/read-str b)

Also, graphql endpoints are suppose to support application/json: http://graphql.org/graphql-js/graphql-clients/.

macluck commented 7 years ago

Hey, I agree with decoursin, this is something that should be taken into consideration in your own code :)

nrakochy commented 7 years ago

Okay, sounds good. I do think there is a use case for requests coming across the wire for clients that have no concept of Graphql that could be converted by venia directly. Nevertheless, I do appreciate the input. Thanks for the reply.