I had thought the ::pco/output needed to specify any nested data that is returned, but I see Pathom manages to figure the nested data out on its own, even when I don’t describe the nesting. I’m curious how this is happening, and if its more efficient to specify the nesting.
Thanks much, all the description you have here is very helpful. I will make sure the ::pco/outputs also contain the structure as I’m using Malli to build it automatically anyway.
same way pathom figures out an omitted pco/output entirely I guess?
depends really, it is preferable that you always be complete with your output (include nested shapes)
when your resolver last form is a map, Pathom can infer the output from that
the thing you see Pathom figuring nested data will depend on usage, you may have a different result if you used nested inputs, for instance:
(ns demos.demo-required-nested
(:require [com.wsscode.pathom3.connect.indexes :as pci]
[com.wsscode.pathom3.connect.operation :as pco]
[com.wsscode.pathom3.interface.eql :as p.eql]))
(def users
{1 {:user/name "A"
:user/score 10}
2 {:user/name "A"
:user/score 20}})
; output all users, just the ids
(pco/defresolver all-users [{::keys []}]
{::pco/output
[:system/all-users]}
{:system/all-users
(mapv #(array-map :user/id %) (keys users))})
(pco/defresolver user-by-id [{:keys [user/id]}]
{::pco/output
[:user/name :user/score]}
(get users id))
(def env
(-> (pci/register
[all-users
user-by-id])))
(comment
; works fine
(p.eql/process env [{:system/all-users [:user/score]}]))in the previous example, not having the full output at all-users works fine, but lets try extend this example to have a resolver that makes a sum of all the scores:
(ns demos.demo-required-nested
(:require [com.wsscode.pathom3.connect.indexes :as pci]
[com.wsscode.pathom3.connect.operation :as pco]
[com.wsscode.pathom3.interface.eql :as p.eql]))
(def users
{1 {:user/name "A"
:user/score 10}
2 {:user/name "A"
:user/score 20}})
; output all users, just the ids
(pco/defresolver all-users [{::keys []}]
{::pco/output
[:system/all-users]}
{:system/all-users
(mapv #(array-map :user/id %) (keys users))})
(pco/defresolver user-by-id [{:keys [user/id]}]
{::pco/output
[:user/name :user/score]}
(get users id))
(pco/defresolver all-scores [{:keys [system/all-users]}]
{::pco/input
[{:system/all-users
; we need to specify this here, otherwise we would get only the ids
[:user/score]}]}
{:system/sum-all-user-scores
(transduce (map :user/score) + 0 all-users)})
(def env
(-> (pci/register
[all-users
user-by-id
all-scores])))
(comment
; fails with: Pathom can't find a path for the following elements in the query: [:user/score] at path [:system/all-users]
(p.eql/process env [:system/sum-all-user-scores]))now if we go back to all-users and fix the output definition to specificy it has :user/id inside, it works:
(ns demos.demo-required-nested
(:require [com.wsscode.pathom3.connect.indexes :as pci]
[com.wsscode.pathom3.connect.operation :as pco]
[com.wsscode.pathom3.interface.eql :as p.eql]))
(def users
{1 {:user/name "A"
:user/score 10}
2 {:user/name "A"
:user/score 20}})
; output all users, just the ids
(pco/defresolver all-users [{::keys []}]
{::pco/output
[{:system/all-users
[:user/id]}]}
{:system/all-users
(mapv #(array-map :user/id %) (keys users))})
(pco/defresolver user-by-id [{:keys [user/id]}]
{::pco/output
[:user/name :user/score]}
(get users id))
(pco/defresolver all-scores [{:keys [system/all-users]}]
{::pco/input
[{:system/all-users
; we need to specify this here, otherwise we would get only the ids
[:user/score]}]}
{:system/sum-all-user-scores
(transduce (map :user/score) + 0 all-users)})
(def env
(-> (pci/register
[all-users
user-by-id
all-scores])))
(comment
; now its fine
(p.eql/process env [:system/sum-all-user-scores]))this is because when dealing with nested inputs, Pathom will try to make sure its possible to reach the nested requirements, this can remove impossible paths from the game, or even avoid querying the parent thing completely unless it sees a viable path
so the rule of thumb is: give Pathom the max info on structure as you can