Skip to content

Instantly share code, notes, and snippets.

@dvingo
Last active September 7, 2022 23:12
Show Gist options
  • Save dvingo/95e3dc2be3d7d1629079f459b9086a1e to your computer and use it in GitHub Desktop.
Save dvingo/95e3dc2be3d7d1629079f459b9086a1e to your computer and use it in GitHub Desktop.
Using sieppari to handle the logic in pathom resolvers and mutations
(ns space.matterandvoid.pathom-sieppari
(:require
[sieppari.context]
[sieppari.core :as s]
[taoensso.timbre :as log]))
(defn terminate-if
"Takes a function that will be passed the pathom enviroment, if that function returns a non-falsey value
the sieppari chain is terminated and whatever is returned from `f` is the response of the chain.
Returning nil or false allows the interceptor chain to continue processing."
[f]
(fn [pathom-env]
(if-let [response (f pathom-env)]
(sieppari.context/terminate pathom-env response)
pathom-env)))
(defn response-interceptor
"Takes function which is invoked with the env/context, whatever is returned from `f` is used as the :response.
Intended to be used to return the final value of an interceptor chain, will set the :response key on the interceptor context."
[f]
{:enter (fn [env] (assoc env :response (f env)))})
(defn terminate [env resp] (sieppari.context/terminate env resp))
(defn interceptors->resolve-fn
"Takes a vector of sieppari interceptors and returns a function that matches the signature for a resolver in pathom 2
i.e.: (fn [env params]), when the returned function is invoked it executes the interceptors chain using sieppari.core/execute.
The interceptors only accept one map as context, thus the pathom params (the 2nd argument supplied to resolve/mutate)
is assoc'ed onto the pathom env to construct the sieppari interceptors context.
"
[ints]
(assert (vector? ints) "Interceptors must be a vector.")
(fn [env params]
(let [r
(:response (s/execute-context ints (assoc env :params params)))]
(def r' r)
r)))
(comment
((interceptors->resolve-fn [
(response-interceptor resp)
{:enter (fn [c] (log/info "enter: ") c)}
{:leave (fn [c] (log/info "leave: ") c)}
])
{:hi 5} nil)
(def inc-x-interceptor
{:enter (fn [{:keys [request] :as ctx}]
(println "ctx: " ctx)
(def c' ctx)
(update-in ctx [:x] inc))})
(defn another-handler [r] {:another-handler true})
(comment
(s/execute-context [inc-x-interceptor
{:enter #(do (println "i 1")
(assoc % :asbd 400))}
{:enter #(do (println "i 2") (assoc % :as2bd 400))}
{:enter #(sieppari.context/terminate % {:done true})}
{:enter #(do (println "i 3") (assoc % :as3bd 300))}
{:enter #(do (println "i 4") (assoc % :as4bd 400))}
{:enter #(do (println "i 5") (assoc % :as5bd 500))}
] {:x 40}
)
(s/execute [{:enter #(update-in % [:request :x] inc)}
{:enter #(do (println "i 1 " %) (assoc % :asbd 400))}
{:enter #(do (println "i 2") (assoc % :as2bd 400))}
{:enter #(sieppari.context/terminate % {:done true})}
{:enter #(do (println "i 3 2 ") (assoc % :as3bd 300))}
{:enter #(do (println "i 4") (assoc % :as4bd 400))}
{:enter #(do (println "i 5") (assoc % :as5bd 500)
(assoc % :response {:done :yes}))}]
{:x 40}))
(s/execute [inc-x-interceptor handler another-handler] {:x 40})
(s/execute-context
[inc-x-interceptor handler #_another-handler] {:x 40})
)
;;; and sample usage
(defn assoc-habit-tx-data [{:keys [current-user params] :as env}]
(let [habit (habit/make-habit params)
new-user (user/add-habit-id current-user habit)
habit (habit/make-db-habit habit)
tx-data (mapv #(do [::xt/put %]) [habit new-user])]
(assoc env :tx-data tx-data :habit habit)))
(def assoc-habit-tx-data-int {:enter assoc-habit-tx-data})
(defn submit-tx [{:keys [xtdb-node tx-data]}]
(assert (valid-xtdb-tx-data? tx-data))
(log/info "Saving tx data: " tx-data)
(xt/submit-tx xtdb-node tx-data))
(def submit-tx-int {:enter submit-tx})
(defn save-habit-response [{:keys [habit]}] habit)
(def save-habit-response-interceptor (interceptors/response-interceptor save-habit-response))
(defn save-habit-ints []
[interceptors/check-logged-in-interceptor
validate-habit-int
assoc-habit-tx-data-int
submit-tx-int
save-habit-response-interceptor])
(def save-habit
{::pc/sym `save-habit
::pc/mutate (interceptors->resolve-fn (save-habit-ints))})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment