Anyone aware of a Pathom resolver that allows to walk the file system or a git repo?
I've heard of none, but what's the use case? Putting a pathom interface in front of things may or may not add any value
It’s a very specific one 🙂
I want to be able to browse files in my new web framework haha
I want to do this without leaking implementation details in my view (the whole reason of using Pathom I believe)
So i was thinking of starting with something simple like a file browser
Maybe someone else was crazy enough to do this as well
I guess not 🙈
Any feedback on this? I want it to work recursively, but I’m still trying to get that to work
@jeroenvandijk hello, first I like to suggest you to use the simple parser instead of parallel, will be faster for this case. And I guess looking at the code that you can do recursive calls already, you can try this query:
(clojure.pprint/pprint
(async/<!! (parser {::p/entity {:file/path "."}}
'[:file/path
:file/type
{:dir/files ...})))
thank you! It’s not resolving the :dir/files
recursively. I think I should add some join functionality somewhere. Reading that documentation now, but it didn’t click yet for me
This is the output. I would expect/hope ./src
and ./git
to be expanded
{:file/path ".",
... nil,
:file/type :dir,
:dir/files
[#:file{:path "./project.clj"}
#:file{:path "./.gitignore"}
#:file{:path "./.nrepl-history"}
#:file{:path "./.git"}
#:file{:path "./src"}]}
@jeroenvandijk I wrote my version of it, this works:
(pc/defresolver file-resolver [env {:file/keys [path]}]
{::pc/input #{:file/path}
::pc/output [:file/type]}
(let [f (<http://clojure.java.io/file|clojure.java.io/file> path)
dir? (.isDirectory f)]
{:file/type (if dir? :dir :file)
:file/dir? dir?}))
(pc/defresolver directory-files-resolver [env {:file/keys [path dir?]}]
{::pc/input #{:file/path :file/dir?}
::pc/output [{:dir/files [:file/path]}]}
(if dir?
{:dir/files
(mapv (fn [^File f0] {:file/path (.getPath f0)})
(.listFiles (<http://clojure.java.io/file|clojure.java.io/file> path)))}))
(def my-resolvers [file-resolver directory-files-resolver])
(def parser
(p/parser
{::p/env {::p/reader [p/map-reader
pc/reader2
pc/open-ident-reader
p/env-placeholder-reader]
::p/placeholder-prefixes #{">"}}
::p/mutate pc/mutate
::p/plugins [(pc/connect-plugin {::pc/register my-resolvers})
p/error-handler-plugin
p/request-cache-plugin
p/trace-plugin]}))
(comment
(parser {} [{[:file/path "src"]
[:file/path
:file/type
{:dir/files '...}]}]))
wow @wilkerlucio thank you!
So I guess my version didn’t trigger the recursion because :dir/files
was already in the returning map, right?
I don't think that's the issue, your code seems like it should work
but your initial query example was off
was missing the map on the join for :dir/files
:dir/files [* {:dir/files [*]}]
☝️ missing {}
around
Ah thank you. Good to understand this 🙂
you are right, my query was wrong. The resolver was working
I guess it is in general a best practise to make your resolvers as small as possible. For reusability and maybe also for performance?
From the docs:
Pathom will scan through the defined resolvers in order to try to satisfy all of the properties in a query. So, technically you can split up your queries as much as makes sense into separate resolvers, and as long as the inputs are in the context Pathom will assemble things back together.
I guess my resolver was indeed not lazy enoughThanks @wilkerlucio. You have created an amazing library. Looking forward to use it more
Is it possible to have context dependent resolvers? E.g. when I want to browse a git tree {:dir/files …}
would need to trigger a different resolver than when I browse a normal file system. I could also use a different key for that, but it would require more knowledge of the user
I think I have an idea 🙂
I think this will work when I implemented
(pc/defresolver file-resolver [{:keys [:resolvers.file/root-dir] :as env} {:file/keys [path]}]
{::pc/input #{:file/path}
::pc/output [:file/type]}
(let [f (<http://clojure.java.io/file|clojure.java.io/file> (str root-dir) path)
dir? (.isDirectory f)]
{:file/type (if dir? :dir :file)
:file/dir? dir?
:filesystem/type :normal}))
(pc/defresolver directory-files-resolver [{:keys [:resolvers.file/root-dir] :as env} {:file/keys [path dir?] filesystem-type :filesystem/type}]
{::pc/input #{:file/path :file/dir? :filesystem/type}
::pc/output [:dir/files]}
(let [relativy (if root-dir
(let [idx (count root-dir)]
(fn [path]
(subs path idx)))
identity)]
(if (= filesystem-type :normal)
{:dir/files
(when dir?
(mapv (fn [^java.io.File f0] {:file/path (relativy (.getPath f0))})
(.listFiles (<http://clojure.java.io/file|clojure.java.io/file> root-dir path))))}
(throw (ex-info "not implemented yet" {}))
)))
When I write a different resolver for a git filesystem the user doesn’t have to know it’s querying something different 🙂@jeroenvandijk you can just make multiple resolvers for the same key as well, and in the case out of context you return nil on the resolver, so pathom will try the other one
Ah awesome!
Hello, is there an acceptable way to access the parser from within a mutation? I have two use cases for this: 1. Resolve unknown information that a mutation needs to function, that the caller of the mutation does not know. 2. Have a mutation submit several other "sub-mutations" to make smaller, reusable mutations For context, my problem domain is interfacing with the Discord API. So for example, for a higher level feature, I might need to make several "sub-mutations" (create post, add a reaction, etc). I also dont want to burden callers of the mutation with knowing details. For example, instead of requiring the "create post" mutation to accept a :discord.channel/id parameter, it would be more convenient to accept a :discord.channel/name and resolve the id based on an existing resolver. Am I thinking about this completely wrong?
@reilysiegel there's :parser
key in env
already
Thank you! So in that case the solution to 2 is obvious, and for 1 I could pass the parameter map as the context to the resolver, and the desired parameters as a query.
In fact, I could probably write a transform that automatically does that based on ::pc/params
a note to consider sub-mutations vs one composite mutation if you're using fulcro: each individual mutation may receive some data from server so your client db is updated - all the updates may be hard to denoted with a composite mutation
also, sub-mutations can "co-ordinate" by using tempids
anyway, both ways are valid, just evaluate the tradeoffs
I was going to try out the latest pathom release 2.3.0-alpha9
. Upon updating to that release from 2.2.30
, I receive an exception trying to load a ns that uses pathom:
Syntax error (ClassNotFoundException) compiling at (com/fulcrologic/guardrails/config.cljc:17:1).
com.google.javascript.jscomp.CompilerOptions
From the changelog I saw 2.3.0-alpha4 bumped the dep that appears to be causing this issue - guardrails. I tried running with 2.3.0-alpha4 instead and received the same issue. I went all the way back to 2.3.0-alpha1 and still get the exception.@kenny just a generic workaround: have you tried :exclusions
in your dependencies?
Wasn’t worth the time to try it out. That’s probably the solution though. One of pathom’s deps updated and now conflicts with something else.
@kenny I wonder if has something to do with cljs versions itself, are you running on a recent one?
This isn't on a cljs app. It's a dep on a Clojure backend service.
I suppose cljs could be brought in accidentally.
maybe, what makes me think around that is because the error seems go be around some missing google closure thing
and from the deps jump you did, guardrails is a new dep
The line of code the exception is pointing to also has this comment:
;; This isn't particularly pretty, but it's how we avoid
;; having ClojureScript as a required dependency on Clojure