Fork me on GitHub
#pathom
<
2020-02-27
>
yenda17:02:40

In the docs I can see how to send queries to graphql without fulcro but I don't understand what facilities pathom offers for parsing the graphql response

wilkerlucio18:02:29

@yenda welcome 🙂 can you tell more about what you mean on parsing graphql response?

yenda18:02:44

So I have a re-frame app and I would like to use pathom without fulcro, since I already have a graphql backend I started with the front end, using pathom to query the local state. Now I'd like to explore using it to manage it as well. Currently I have graphql queries as string that I send with axios and denormalize the data "manually". I am playing with query->graphql and it seems to work fine with some tuning to query the endpoint, and I'm wondering if there is an equivalent graphql->query to convert the response to EQL.

wilkerlucio18:02:25

@yenda gotcha, yeah, the query->graphql is something pathom uses internally, I should rename this page here: https://wilkerlucio.github.io/pathom/v2/pathom/2.2.0/graphql/fulcro.html

wilkerlucio18:02:44

altough its named fulcro, this works for anything (just ignore the fulcro remote and UI parts, all the rest should be same, the parser configuration is what matters to you here)

wilkerlucio18:02:07

if you go with the connect part, you can even extend your GraphQL things on the pathom side (created dynamic computations on top of what graphql provides)

yenda18:02:57

Ok I'm exploring this, I think that my biggest pain point is to figure how to fill the ident-map, because the endpoint uses attributes like "user_id" "user_name" which translates to "user/id", "user/name" in the app

yenda18:02:19

I had to do the following to generate a valid query:

(defn js-name [k]
  (if (qualified-keyword? k)
    (str (namespace k) "_" (-> k
                               name
                               pg/camel-case))
    k))

(defn ident-transform [[key value]]
  (let [fields [(str (namespace key) "_" (-> key
                                             name
                                             pg/camel-case))]
        value  (if (vector? value) value [value])]
    (if-not (= (count fields) (count value))
      (throw (ex-info "The number of fields on value needs to match the entries" {:key key :value value})))
    {::pg/selector (-> (namespace key) (clojure.string/split #"\.") last)
     ::pg/params   (zipmap fields value)}))

#_(println (pg/query->graphql [{[:user/id "5503438a-583f-11ea-99f8-0242c0a82002"]
                                [:user/id :user/name :user/photo  :user/is-current-user-following]}]
                              {::pg/ident-transform
                               ident-transform ::pg/js-name js-name}))

yenda18:02:34

not sure how to get the same with the parser

yenda19:02:31

This is what I'm trying atm:

(def remote-gql
  {::pcg/url       ""
   ::pcg/prefix    "remote"
   ::pcg/mung      clj->gql
   ::pcg/demung    gql->clj
   ::pcg/ident-map {"user"       {"user_id" :remote.user/id}}
   ::p.http/driver request-async})

(take! (pcg/load-index remote-gql) #(reset! indexes %))

(def remote-parser
  (p/parallel-parser
   {::p/env     {::p/reader               [p/map-reader
                                           pc/parallel-reader
                                           pc/open-ident-reader
                                           p/env-placeholder-reader]
                 ::p/placeholder-prefixes #{">"}
                 ::p.http/driver          request-async}
    ::p/mutate  pc/mutate-async
    ::p/plugins [(pc/connect-plugin {; we can specify the index for the connect plugin to use
                                        ; instead of creating a new one internally
                                     ::pc/indexes  indexes})
                 p/error-handler-plugin
                 p/trace-plugin]}))

(take! (remote-parser {} [{[:remote.user/id "5503438a-583f-11ea-99f8-0242c0a82002"]
                           [:remote.user/id :remote.user/name :user/photo]}]) println)

yenda19:02:55

and I get {[:remote.user/id 5503438a-583f-11ea-99f8-0242c0a82002] {:remote.user/id 5503438a-583f-11ea-99f8-0242c0a82002, :user/photo :com.wsscode.pathom.core/not-found, :remote.user/name :com.wsscode.pathom.core/not-found}}

yenda19:02:37

request-async is just the regular one but I added a print to see which request is sent, seems like it doesn't send any

yenda19:02:32

I can see the indexes loaded properly

yenda19:02:23

mhm okay so I get a result with

(take! (remote-parser {} [{[:remote.User/user_id "5503438a-583f-11ea-99f8-0242c0a82002"]
                           [:remote.User/user_id :remote.User/user_name :remote.User/user_photo]}]) println)

yenda19:02:30

is there a way to add some headers to the http driver?

yenda20:02:00

ok as simple as passing ::http/headers to the env of the parser

yenda20:02:50

is there a way to "fallback" on the remote parser when the local one doesn't find something?