I was working on how to organize resolver code - mainly for common concerns like auth and made an interesting connection - combining pedestal interceptors with pathom-connect transform....
(require
[io.pedestal.interceptor.chain :as chain]
[io.pedestal.interceptor.helpers :as ih])
(def response-key :pathom-interceptors/response)
(defn assoc-response [in-map response]
(assoc-in in-map [:env response-key] response))
(defn get-response [in-map]
(get-in in-map [:env response-key]))
(defn response-interceptor
[{:keys [opts env params] :as in}]
(let [{::pc/keys [mutate resolve]} opts
response (get-response in)]
(if response
in
(if resolve
(assoc-response in (resolve env params))
(assoc-response in (mutate env params))))))
(defn interceptors->pathom-transform
"Executes vector of interceptors on a pathom resolver or mutation.
Each interceptor is passed a single map (the environment) which has the keys:
:opts - The definition-time pathom resolver or mutation map of options.
:env - The pathom connect environment for the resolver or mutation passed by pathom at request-time.
:params - The params to the resolver or the mutation.
Responses are set on the env like so:
(assoc-response env {:my-pathom-resp :value})
"
[interceptors]
(fn pathom-transform*
[{::pc/keys [mutate resolve] :as opts}]
(let [interceptors (conj interceptors (ih/after response-interceptor))]
(cond
resolve
(assoc opts ::pc/resolve
(fn [en params]
(let [out (chain/execute {:opts opts :env en :params params} interceptors)]
(get-response out))))
mutate
(assoc opts ::pc/mutate
(fn [en params]
(let [out (chain/execute {:opts opts :env en :params params} interceptors)]
(get-response out))))
:else (throw
(Exception.
(str "Attempting to use interceptor transform on a map that does not have a resolve or mutate.")))))))
(defn auth-user-interceptor
[{:keys [opts env] :as in}]
(let [{:auth/keys [no-user-msg]
:or {no-user-msg "You must be logged in to perform this action."}} opts
{:keys [current-user]} env]
(cond-> in (not current-user)
(assoc-response (server-error no-user-msg)))))
(pc/defmutation create-thing-mutation
[{:keys [current-user] :as env} props]
{:auth/no-user-msg "You must be logged in to create a thing."
::pc/transform (interceptors->pathom-transform [(ih/before auth-user-interceptor)])}
;; do mutation
)