Skip to content

Instantly share code, notes, and snippets.

@dvingo
Created September 13, 2022 19:28
Show Gist options
  • Save dvingo/213633acfdd520bddcdc91fc1c7b9e44 to your computer and use it in GitHub Desktop.
Save dvingo/213633acfdd520bddcdc91fc1c7b9e44 to your computer and use it in GitHub Desktop.
given a malli schema for a domain entity (a hashmap) produce a pathom output vector.
(ns my-app.malli.transform.pathom
(:refer-clojure :exclude [uuid])
(:require
[malli.core :as m]
[taoensso.timbre :as log]))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; helpers
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(def recur-types #{:map :vector})
(defn recur-type? [value]
(assert (contains? value :type) "You need to pass in a proper malli ast (with a :type key).")
(contains? recur-types (:type value)))
(defn ref-type? [{:keys [value]}]
(log/trace "checking ref type : " value)
(def value' value)
(when value
(m/-ref-schema? (m/schema value))))
(defn get-id-prop
"Return property that has the tag ::db/identity? else the first property whose keyword name part is `id`"
[identity-kw schema-keys-map]
(let [id (ffirst (filter (fn [[_ v]] (some-> v :properties identity-kw)) schema-keys-map))]
(if id id
(first (filter (fn [k] (some-> k name (= "id"))) (keys schema-keys-map))))))
(defn schema->id-prop*
([id-kw ?s]
(condp = (:type ?s)
:map
(ffirst (filter
(fn [[k {:keys [properties]}]]
(println "filtering: " k )
(println "props: " properties )
(if id-kw
(when (id-kw properties)
(do
(println "have id-kw: " id-kw)
(println "props: " properties)
k))
(some-> k name (= "id"))))
(:keys ?s)))
;(reduce-kv (fn [acc k {:keys [order value]}]
; (cond (recur-type? value)
; acc
;
; (ref-type? value)
; (let [child-ast (m/ast (m/deref (:value value)))]
; (if (recur-type? child-ast)
; acc k)
; )
;
; ))
;
; [] (:keys ?s))
:and
(let [map-children (filter (comp #{:map} :type) (:children ?s))]
(assert (= (count map-children) 1) "Must only be one :map child for :and.")
(log/info "parsing and: " ?s)
(log/info "parsing and: " map-children)
(schema->id-prop* id-kw (first map-children)))
))
)
(defn schema->id-prop [id-kw ?schema]
(schema->id-prop* id-kw (m/ast ?schema)))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; parsing multi-method
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defmulti parse-ast-to-pathom-output :type)
(defmethod parse-ast-to-pathom-output :default [{:keys [value]}] value)
(defmethod parse-ast-to-pathom-output :uuid [ast])
(defmethod parse-ast-to-pathom-output :local-date [ast])
(defmethod parse-ast-to-pathom-output :enum [ast])
(defmethod parse-ast-to-pathom-output :vector [{:keys [child properties]}]
(def child' child)
(def properties' properties)
(log/trace "child: " child)
(let [{child-key :value} child
child-ast (m/ast (m/deref (m/schema child-key)))
schema-keys-map (:keys child-ast)
id (util/get-id-prop ::db/identity schema-keys-map)]
(log/trace "id: " id)
[id]))
(defmethod parse-ast-to-pathom-output :and
[{:keys [children] :as ast}]
(let [map-children (filter (comp #{:map} :type) children)]
(assert (= (count map-children) 1) "Must only be one :map child for :and.")
(log/info "parsing and: " ast)
(log/info "parsing and: " map-children)
(parse-ast-to-pathom-output (first map-children))))
(defmethod parse-ast-to-pathom-output :map
[{:keys [keys]}]
(log/trace "keys: " keys)
;; for each key in the keys children call parse-ast-to-pathom-output
(let [out (reduce-kv
(fn [acc k {:keys [order value] :as v}]
(assoc acc order
(do
(log/trace "value: " (:value value))
(try
(log/trace " deref: " (m/deref (:value value)))
(catch #?(:clj Exception :cljs :default) e))
;(log/debug "type: " (:type value) " recur ype: " (util/recur-type? value))
;(log/debug "ref type?: " (util/ref-type? value))
(cond
(util/recur-type? value) {k (parse-ast-to-pathom-output value)}
(util/ref-type? value) (do
;(log/debug "recur with ref: " (m/ast (m/deref (:value value))))
(let [child-ast (m/ast (m/deref (:value value)))]
(if (util/recur-type? child-ast)
{k (parse-ast-to-pathom-output child-ast)}
k)))
:else k))))
[]
keys)]
out))
(defn schema->pathom-output [?schema]
(parse-ast-to-pathom-output
(m/ast ?schema)))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment