pathom

Yab Mas 2024-06-24T08:39:37.297459Z

Not super experienced with pathom and struggling with something that I would expect to come up regularly: I have: • A base resolver that returns a collection of entities. E.g. {::pco/output [{:xs [:x]}]} • A bunch of other resolvers that are able to provide extra properties. E.g. {::pco/input [:x] ::pco/output [:y]} Now I want to filter the collection if a certain config is set. The filtering happens based on some of the properties that are added outside the base resolver (if it happend on some of the base props I would have simply done the filtering in the base resolver). My first intuition is to create a filtered-xs resolver. E.g. {::pco/input [{:xs [:y]}] ::pco/output [:filtered-xs]} I want to be able to query filtered-xs in the same way as I can with xs; only difference being that all entities with a certain value of :y are removed from the result. But I run into the following problems: • Given the signature above I'm unable to resolve the query [{:filtered-xs [:z]}] even though [{:xs [:z]}] works fine. • Changing the signature (and implementation) to {::pco/input [{:xs [:y :z]}] ::pco/output [:filtered-xs]} does unable me to resolve the above query but: ◦ Now :z will always be resolved even if it's not queried for. ◦ It generally feels like an anti-pattern to add props that have nothing to do with what's happening in this resolver. ◦ Adding attributes to input to unable a certain output in this case is probably wrong all together, but again I'm not super experienced and just trying to understand how things work. Any guidance would be really appreciated 🙏

Thomas Moerman 2024-06-24T09:23:37.848829Z

> Now I want to filter the collection if a certain config is set. What kind of config do you mean? At first sight, I guess you might want to take a look at resolver parameters: https://pathom3.wsscode.com/docs/resolvers#parameters

Yab Mas 2024-06-24T10:48:28.625979Z

Getting the config is actually not the problem. It's the "I want to filter the collection that's returned by a resolver based on a property that's added to the entities by another resolver"

souenzzo 2024-06-24T11:44:20.262049Z

seems like a bug at first glance. I used to do that in pathom2

Thomas Moerman 2024-06-24T11:52:48.380539Z

This appears to work:

(let [_ (pco/defresolver xs
          [{} {}]
          {:xs [{:x 1 :z 1}
                {:x 2 :z 2}
                {:x 3 :z 3}]})

      _ (pco/defresolver x=>y
          [{} {:keys [x]}]
          {:y (even? x)})

      _ (pco/defresolver x=>z
          [{} {:keys [x]}]
          {:z (str x)})

      _ (pco/defresolver filtered-xs
          [{} {:keys [xs]}]
          {::pco/input [{:xs [:x :y]}]
           ::pco/output [:filtered-xs]}
          {:filtered-xs (filter (fn [{:keys [y]}] y) xs)})

      env (pci/register {} [xs x=>y x=>z filtered-xs])]
  
  (p.eql/process env [{:filtered-xs [:x :z]}]))

=> {:filtered-xs ({:x 2, :z "2"})}

Yab Mas 2024-06-24T12:07:05.269679Z

Interesting.. Can confirm your example runs for me as well and this is indeed the behaviour Im looking for. But I dont immediately see what Im doing wrong in mine.

(def x->y
  {:x1 :y1 :x2 :y2 :x3 :y3})

(def x->z
  {:x1 :z1 :x2 :z2 :x3 :z3})

(pco/defresolver xs-resolver
  [_ _]
  {::pco/output [{:xs [:x]}]}
  {:xs [{:x :x1} {:x :x2} {:x :x3}]})

(pco/defresolver x->y-resolver
  [_ {:keys [x]}]
  {::pco/input [:x]
   ::pco/output [:y]}
  (prn "resolving Y")
  {:y (x->y x)})

(pco/defresolver x->z-resolver
  [_ {:keys [x]}]
  {::pco/input [:x]
   ::pco/output [:z]}
  (prn "resolving Z")
  {:z (x->z x)})

(pco/defresolver filtered-xs-resolver
  [env input]
  {::pco/input [{:xs [:y]}] ::pco/output [:filtered-xs]}
  (def _env env)
  (def _input input)
  (let [xs (:xs input)]
    {:filtered-xs (filterv (fn [{:keys [y]}] (not= y :y2)) xs)})) 
(p.eql/process env [{:filtered-xs [:y :z]}])

=> Execution error (ExceptionInfo) at com.wsscode.pathom3.connect.planner/verify-plan!* (planner.cljc:1688).
Pathom can't find a path for the following elements in the query: [:z] at path [:filtered-xs 0]

Yab Mas 2024-06-24T12:18:53.338059Z

It's the addition of :x to the input of the filter resolver, if I change mine to {::pco/input [{:xs [:x :y]}] ::pco/output [:filtered-xs]} it works as well.. which doesn't immediately make sense to me 🤔

Thomas Moerman 2024-06-24T12:28:48.004539Z

I guess pathom can find a :y given an :x, but not an :x given a :y, the :x being required to find the :z

Yab Mas 2024-06-24T12:31:48.895019Z

But it knows :x is contained in the output of :xs right?

Yab Mas 2024-06-24T12:32:32.244379Z

Anyway I'm going to try and fix the actual app with this new info

Yab Mas 2024-06-24T13:45:03.539559Z

Ok, I'll have to test a bit more but I think I've got it working. It still doesn't make too much sense to me though. I'm a bit out of depth wrt how this works behind the scenes; and wheter this behaviour is strictly/technically needed or a design choice. But to me it feels like unneeded duplication and mental dependency-tracking that pathom should be able to do for me. Really appreciate the help though!