Question - how could I auto-reload my rad resolvers at dev-time?
auto-reload? You probably mean re-def a resolver and have it take effect without restarting, right?
I make my own macros (defresolver/mutation) in CLJ for server-side. The macro outputs a defn AND the resolver, but the resolver just calls the defn. That way when I re-eval the macro it rewrites that same function, and since the pathom parser has closed over the resolver that CALLS that function, that makes it work just like re-eval of defn.
I also add a hook into defmutation that updates my RAD database atom so that a mutation with a return query works properly
(the db is in the env so all resolvers work on the same version of the db, but that needs to update on a mutation)
Yes. without restarting the server
just a sec…let me strip out some stuff and I’ll send you the basic pattern
(ns pathom.connect-macros
(:require
[com.fulcrologic.rad.database-adapters.datomic-options :as do]
[festivar.lib.pathom.registry]
[clojure.spec.alpha :as s]
[com.fulcrologic.fulcro.algorithms.do-not-use :as futil]
[com.wsscode.pathom.connect :as pc]))
;; Use @registry as your resolvers in pathom parser def...just make sure you require all nses that define resolvers/mutations in that ns
;; so they all get into the registry first.
(defonce registry (atom []))
(defn register! [resolver] (swap! registry conj resolver))
(defn update-database-atoms! [env]
(doseq [dbk (keys (get env do/databases))
:let [dbatom (get-in env [do/databases dbk])
conn (get-in env [do/connections dbk])]]
(reset! dbatom (d/db conn))))
(s/def ::check (s/or :sym symbol? :expr list?))
(s/def ::mutation-args (s/cat
:sym simple-symbol?
:doc (s/? string?)
:arglist vector?
:config map?
:body (s/* any?)))
(defn defpathom-backend-endpoint* [endpoint args update-database?]
(let [{:keys [sym arglist doc config body]} (futil/conform! ::mutation-args args)
internal-fn-sym (symbol (str (name sym) "__internal-fn__"))
nspc (if (namespace sym) sym (name (ns-name *ns*)))
fqsym (symbol nspc (name sym))
env-arg (first arglist)
params-arg (second arglist)
update-dbatom (when (or update-database? (= endpoint `pc/defmutation))
`(update-database-atoms! ~env-arg))]
`(do
;; Use this internal function so we can dynamically update a resolver in
;; dev without having to restart the whole pathom parser.
(defn ~internal-fn-sym [env# params#]
(let [~env-arg env#
~params-arg params#
result# (do ~@body)]
~update-dbatom
;; Pathom doesn't expect nils
(cond
(sequential? result#) (vec (remove nil? result#))
(nil? result#) {}
:else result#)))
(~endpoint ~(cond-> sym
doc (with-meta {:doc doc})) [env# params#]
~config
(~internal-fn-sym env# params#))
(register! ~sym) ; side effect the resolver into a shared atom that I can defer into pathom config
::done)))
(defmacro defmutation [& args] (defpathom-backend-endpoint* `pc/defmutation args true))
(defmacro defresolver [& args] (defpathom-backend-endpoint* `pc/defresolver args false))
https://gist.github.com/awkay/f70d3c872ed40a94e2fcd923eb4436f3
no guarantees that compiles perfectly, but it should
thanks3 @tony.kay! Finally got around to trying this today. IT WORKED!!!!!
It is missing the [datomic.client.api :as d] require.
@tony.kay nice you removed the warning about PREFIX I had dozens of those 😄