Fork me on GitHub
#pathom
<
2023-08-31
>
plexus09:08:57

hey folks, pretty new to Pathom so please ignore my ignorance 🙂 is there a way to access inputs from a parent resolver? what I'm dealing with is a set of resolvers that proxy to a third party API, for which the caller provides an API key in the EQL input data. I can access that api key in the top-level resolver, but when I try to resolve nested data I'm stuck.

plexus11:08:57

a more concrete example, say I have users which are part of user groups. Users have an id, but the id is only unique within a given group, so to retrieve more information about the user I need both the user id and the group id

plexus11:08:00

(pco/defresolver user-groups []
  {:groups [{:group/id 1}
            {:group/id 2}
            {:group/id 3}]})

(pco/defresolver group-users [{:group/keys [id]}]
  {:group/users [{:user/id (str id "a")}
                 {:user/id (str id "b")}]})

(pco/defresolver user-data [????]
  ;; fetch data for a user based on its group/id and user/id
  {:user/data (fetch-user-data group-id user-id)}
  )

plexus11:08:34

(p.eql/process env [{:groups [{:group/users [:user/id :user/data]}]}])

plexus11:08:19

the only way I've found to make this contextual information available down the tree is to repeat it at every level

plexus11:08:59

(pco/defresolver group-users [{:group/keys [id]}]
  {:group/users [{:user/group-id id
                  :user/id (str id "a")}
                 {:user/group-id id
                  :user/id (str id "b")}]})

pithyless14:08:16

> Users have an id, but the id is only unique within a given group I think there is a hidden "entity" in your description: the "group-membership" (group + user).

{:group/members [{:group-member/id "???"
                  :group-member/user-id 123
                  :group-member/group-id 345}]}
Since you don't have this explicit, you've got an impedance mismatch. So, I think the trick is to just figure out which way to model this invisible entity works best for you and DX ergonomics (instead of thinking how to "pass down" the group-id). :user/group-id feels the least useful (since it's not a property of the user, but of the membership) and I would either pass the values directly:
{:group/users [{:user/id 123, :group/id 345}]}
or maybe even consider creating some custom ID via e.g. a tuple (which may never be exposed publicly, but can still be used to resolve other attributes):
{:group/users [{:group/member [123 345]}]}

plexus11:08:17

is that how people solve this?

wilkerlucio13:08:47

hello @plexus, welcome! as you mentioned, forwarding down is one way, if the user can have only a single group you could also make a resolver to navigate to it. for the token scenario, in general people have it in the env instead of input, so its globally available (but if that info is coming from another resolver, you might need two requests, first to fetch it, then to set it at env for the next requests)

wilkerlucio13:08:37

a third more involved solution would be using a mutable thing at env, there you could set on the resolver return, this could a simple atom application if the thing is global, but if in different sections you need different info, them the atom can be in the format of {PATH THING-VALUE}, you can access the current path from env at any time, so you could have an algorithm that looks for path parts (starting at current and removing from the tail on each iteration, until path is found or reach the root), makes sense?