This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2022-05-30
Channels
- # babashka (7)
- # beginners (25)
- # calva (22)
- # cljs-dev (1)
- # clojure (62)
- # clojure-europe (118)
- # clojure-hamburg (4)
- # clojure-israel (2)
- # clojure-nl (2)
- # clojure-uk (6)
- # clojured (1)
- # clojurescript (23)
- # conjure (11)
- # cursive (3)
- # datomic (14)
- # duct (2)
- # emacs (12)
- # figwheel-main (1)
- # gratitude (1)
- # hyperfiddle (4)
- # joyride (72)
- # lsp (46)
- # luminus (1)
- # malli (1)
- # off-topic (54)
- # pathom (19)
- # polylith (11)
- # releases (2)
- # sci (22)
- # shadow-cljs (4)
- # vim (11)
- # xtdb (52)
How do I update the env with pathom3 in a mutation?
In pathom2 you just returned ::p/env
Hmm… I used that functionality to update the :db
key in my env to :db-after
from the transaction report.
https://clojurians.slack.com/archives/C87NB2CFN/p1626499102252200?thread_ts=1626471981.239700&cid=C87NB2CFN
@U066U8JQJ What would be the right place to put things like the current database value or user session or something…? Currently, I am satisfied with something like this:
(defresolver resolve-user-preferences [{:keys [current-user] :as env} _]
{::pco/inputs []
::pco/output [:user/preferences]}
{:user/preferences (get-preferences env current-user)})
(defmutation register-user [env user]
{::pco/output [:user/id]}
(let [id (register-user! env user)]
{::p/env (assoc env :current-user user)
:user/id id}))
I removed that env feature because it was accidently leaking stuff sometimes, currently I think an option is to have some atom at env that you can modify, if path matters this atom could be something like {[:path] :some-value}
, this way when reading from the env you use the current path to differenciate branches, makes sense? I'm also open to suggestions, just didn't put much though on this problem at Pathom 3 yet
Do mean leaking outside the subgraph? In which situation does this occur? In this case, the atom would leak as well, so you gained nothing over adding the value with the path to the env.
I mean the whole env leaking out in the output data
Hi. I'm trying to figure out how pathom works with nested data and "contexts". I think it would be easier to just show example/reproducer:
(pco/defresolver situations [{:keys [module/id]}]
{::pco/output
[{:module/situations [:situation/id]}]}
{:module/situations [{:situation/id :s1}
{:situation/id :s2}
{:situation/id :s3}]})
(pco/defresolver situation-done [{:keys [situation/id]}]
{::pco/output
[:situation/done]}
{:situation/done true})
(def env
(pci/register [situations
situation-done]))
(comment
(p.eql/process
env
{:module/id :m1}
[{:module/situations [:situation/done]}])
)
=> #:module{:situations [#:situation{:done true} #:situation{:done true} #:situation{:done true}]}
It works as expected. Now I want to add an input to situation-done
resolver, something completely disconnected from situation/id
. And I provide it as initial data.
(pco/defresolver situation-done [{:keys [situation/id user/id]}]
{::pco/output
[:situation/done]}
{:situation/done true})
(p.eql/process
env
{:module/id :m1
:user/id 1}
[{:module/situations [:situation/done]}])
It stops working and says that
Graph execution failed: Pathom can't find a path for the following elements
in the query: [:situation/done] at path [:module/situations 0]
Why? Isn't user/id resolvable in any "context"? Thank you!:user/id
is only visible at the "root node"
The situations are a node down from the root.
Your Graph effectively looks like this:
{:module/id :m1
:user/id 1
:module/situations [{:situation/id :s1}]}
Having the :user/id
on every level would break things
Imagine following situation:
(defresolver resolve-friends [{:keys [user/id]}]
{::pco/output [{:user/friends [:user/id]}]})
(defresolver resolve-user-name [{:keys [user/id]}]
{::pco/output [:user/name]})
(process env {:user/id 42} [{:user/friends [:user/id]}])
If you want something available everywhere use env
Thank you. So, I made wrong assumptions about what pathom (it's funny I made it, but it's out of topic :) ) Could you suggest how to solve situations when I want to keep some context about required data and use it in resolvers? For example, imagine this data structure:
{:room/id :room1
:room/users [{:user/id :user1
:user/name-in-room "User name"}]}
To resolve :user/name-in-room I need two things: room/id and user/id. The only way that I see now it's providing it together with :room/users list, but it reduces composability and, possibly, performance. Not every query could want to get :user/name-in-room but it requires additional requests to get this data.Maybe:
{:room/id :room1
:room/users [#:room+user{:name "User name"
:user {:user/id :user1}
:room {:room/id :room1}}]}
?
(defresolver resolve-room->room+user [{:keys [room/id]}]
{::pco/output [{:room/users [:room+user/user :room+user/room]}]})
(defresolver resolve-user->room+user [{:keys [room/id]}]
{::pco/output [{:user/rooms [:room+user/user :room+user/room]}]})
(defresolver resolve-room+user-name [{:room+user/keys [user room]}]
{::pco/output [:room+user/name]})
I have used this pattern many times, where you forward some data down, so you have the full context you need, something like:
{:room/id :room1
:room/users [{:user/name "User name"
:user/id :user1
:room/id :room1}]}
You cannot destruct both user/id and subscription/id because both of them goes to the symbol id
@U066U8JQJ yes, I came up to the similar principle. But in my case it's not so natural. I have this nested structure for syllabus:
(pco/resolver
`dashboard-self-studies-completed
{::pco/input [:syllabus.situation/id :user/id]
::pco/output [:dashboard.self-studies/completed]})
(pco/resolver
`syllabus-situations
{::pco/input [:syllabus.module/id
(pco/? :user/id)]
::pco/output [{:syllabus/situations [:syllabus.situation/id
:user/id]}]})
(pco/resolver
`syllabus-level
{::pco/input [:syllabus/level
(pco/? :user/id)]
::pco/output [{:syllabus/modules [:syllabus.module/id
:user/id]}]})
syllabus is completely unrelated to the user and I want to keep resolvers this way. But in some queries I want to have data specific to some part of the syllabus AND some user (like :dashboard.self-studies/completed
)
So I'm adding an optional input user/id
to every resolver in upper levels and forward to the downstream.
It's working, but it's a hack.I don't think I quite understand, but if you have syllabus entities that are independent from users, and user entities, and somehow users "own" or "have" some relationship to the syllabus but with extra (meta)information added, then this relationship is it's own entity that you could model
So that you could query somehow like {:user [{:syllabus-relationship [:extra-information {:syllabus [:common-data-for-syllabus]}]}]}
That is what I did with :room+user/name
above.