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 🙏
> 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
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"
seems like a bug at first glance. I used to do that in pathom2
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"})}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]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 🤔
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
But it knows :x is contained in the output of :xs right?
Anyway I'm going to try and fix the actual app with this new info
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!