pathom

:pathom: https://github.com/wilkerlucio/pathom/ & https://pathom3.wsscode.com & https://roamresearch.com/#/app/wsscode
wilkerlucio 2020-05-26T01:52:38.089700Z

@myguidingstar I suggest you use the async-parser for that

wilkerlucio 2020-05-26T01:52:56.089800Z

not sure what you mean, can you give an example?

markaddleman 2020-05-26T03:17:58.090Z

(ns com.wsscode.pathom.book.connect.getting-started2
  (:require [com.wsscode.pathom.core :as p]
            [com.wsscode.pathom.connect :as pc]))


(pc/defresolver people-resolver [_ _]
  {::pc/input  #{}
   ::pc/output [{:people [:name]}]}
  {:people [{:name "Mark"}
            {:name "Joe"}]})

(pc/defresolver address-resolver [_ {:keys [name]}]
  {::pc/input  #{:name}
   ::pc/output [:address]}
  (if (= name "Mark")
    {:address "111 Main St"}))

(def app-registry [people-resolver
                   address-resolver
                   pc/index-explorer-resolver])

(def parser
  (p/parser
    {::p/env     {::p/reader [p/map-reader
                              pc/reader2
                              pc/open-ident-reader]}
     ::p/mutate  pc/mutate
     ::p/plugins [(pc/connect-plugin {::pc/register app-registry})
                  p/error-handler-plugin
                  p/trace-plugin]}))

(parser {} [{:people [:name :address]}])

markaddleman 2020-05-26T03:18:36.090200Z

The result is

{:people [{:name "Mark", :address "111 Main St"} {:name "Joe", :address :com.wsscode.pathom.core/not-found}]}
I'd like to filter out Joe

markaddleman 2020-05-26T03:28:51.090400Z

I suspect that I have to write a plugin to do this. Am I on the right track?

markaddleman 2020-05-26T03:36:40.090600Z

After looking at the plugin architecture, I think that's the wrong approach. Perhaps post-processing the results is the right way

jacklombard 2020-05-26T05:25:26.091200Z

Hey all, how does HTTP/CDN caching work for pathom/transit?ย Can it be done? If yes, is purging the cache straight forward?

2020-05-26T10:12:09.095Z

If you wanted to do http caching of eql queries, you could try passing the eql as a query param. Pathom doesn't specify how eql gets from your client to the server. That is completely up to you.

๐Ÿ‘ 1
2020-05-26T06:04:27.092100Z

@wilkerlucio my question is what else I need to change to use async, given that I use (-> env ::pcp/node) in my dynamic resolver

wilkerlucio 2020-05-26T07:42:38.093400Z

that could be a bug, does it work normally on sync parsers but not on async?

2020-05-26T08:06:07.093600Z

yes, it works on sync

2020-05-26T06:06:09.093300Z

I tried p/parallel-parser and async-parser, but ::pcp/nodereturns nil in both cases, so I guess there's something I miss

2020-05-26T08:10:00.094400Z

my bad, I pass the wrong order of params to resolve function

2020-05-26T08:10:12.094800Z

(-> env ::pcp/node)does work for async parser

Jakub Holรฝ 2020-05-26T14:20:36.095300Z

@wilkerlucio FYI Import of latest v 1.0.10 to cljdoc failed https://cljdoc.org/builds/31120

๐Ÿ‘€ 1
Michael W 2020-05-26T15:51:54.096900Z

Are there any good examples of using the parser? I'm still new to clojure, got my api data sources all wired up into pathom, and now I can't seem to figure out how no run multiple queries and pull the data out. I can do 1, and I get the data in a PersistentArrayMap but I'm kinda lost at that point...

2020-05-26T16:18:45.097900Z

@michael819 you could take a look at pathom's tests.

Michael W 2020-05-26T16:19:29.098700Z

I have been looking at those, but when I run a query I get a map back with the query as the key, but in those tests it looks like there is no key, just a map of results

2020-05-26T16:20:15.099200Z

Also perhaps a little less involved: https://chrisodonnell.dev/posts/giftlist/parser_tests/

2020-05-26T16:20:29.099600Z

How are you calling the parser?

Michael W 2020-05-26T16:21:03.099800Z

(parser {} [{[:ddi/ip "192.168.1.111"] [:ddi/name :ddi/mac :aci/mac]}])
{[:ddi/ip "192.168.1.111"] {:ddi/name "<http://hostname.domain.com|hostname.domain.com>", :ddi/mac "00:25:b5:21:a0:57", :aci/mac "00:25:b5:21:a0:57"}}

2020-05-26T16:22:05.100Z

That looks right to me

2020-05-26T16:22:27.100800Z

The key in your result map is the ident for which you made the query

2020-05-26T16:22:40.101300Z

And the value has all the attributes you queried for

Michael W 2020-05-26T16:22:55.101700Z

Yeah, but in the tests for pathom his = assertions all just have the results, without the ident key

2020-05-26T16:25:14.102600Z

Can you link to a specific test?

Michael W 2020-05-26T16:25:55.102800Z

(is (= (parser {} [:foo])
           {:foo "bar"}))

    (is (= (parser {} [:foo :aa])
           {:foo "bar"
            :aa  :not-found}))

Michael W 2020-05-26T16:27:35.103600Z

All the assertions are just for the results, there is no map key for the ident, which is what confused me.

Michael W 2020-05-26T16:30:00.104300Z

The link you provided is much clearer, I see you using select-keys and get to pull the results out using the ident.

๐Ÿ‘ 1
2020-05-26T16:41:11.105100Z

Those tests aren't using pathom connect, which is why the result structure is different.

2020-05-26T16:44:21.105600Z

I won't recommend looking at pathom's tests in the future; they aren't super helpful for a beginner, it seems! ๐Ÿ˜…

2020-05-26T16:45:29.106700Z

Even the connect tests are mostly verifying internals or seem to be constructed to verify certain bits of behavior rather than to illustrate how the parser is meant to be used.

Michael W 2020-05-26T16:53:20.107400Z

I thought the developer guide was good except that one thing, everything in there doesn't show how to really use the parser.

2020-05-26T17:02:43.111900Z

@michael819 Top level keys like that are another way to use the parser. In my experience they're usually used to get to a set of entities, but they can also be used as global constants (or to do something like inject the current timestamp) as they seem to be in the test you linked. You could reproduce the parser from your test with this resolver:

(defresolver foo-resolver [_ _]
  {::pc/input #{}
   ::pc/output [:foo]}
  {:foo "bar"})

(def parser ...)

(parser {} [:foo])
{:foo "bar"}
Here's an actual resolver from the project the blog post I linked above was talking about that also uses a top level key:
(defresolver created-gift-lists
  [{::db/keys [pool] :keys [requester-id]} _]
  {::pc/input #{}
   ::pc/output [{:created-gift-lists [::gift-list/id]}]}
  {:created-gift-lists
   (db/execute! pool
     {:select [:gl.id]
      :from [[:gift_list :gl]]
      :where [:= requester-id :gl.created_by_id]
      :order-by [:gl.created_at]})})

(def parser ...)

(parser {:requester-id 1} [{:created-gift-lists [::gift-list/id]}])
{:created-gift-lists [{::gift-list/id 1} {::gift-list/id 2}]}

2020-05-26T17:04:53.112300Z

I'm sure Wilker talks about this in at least one of his talks. Maybe this one? https://www.youtube.com/watch?v=IS3i3DTUnAI

2020-05-26T17:09:47.113500Z

@wilkerlucio I have this piece of code that works on clj but somehow slightly incorrect in cljs https://gist.github.com/myguidingstar/6bff072b099cc0d5a178c61f828eb925

2020-05-26T17:12:36.114200Z

I guess it's a bug with async planner in cljs