Builds client SSR approach, sunsets old cljs.
This commit is contained in:
@@ -1,5 +1,8 @@
|
||||
(ns iol-ion.tx.upsert-entity
|
||||
(:require [datomic.api :as dc])
|
||||
(:require [datomic.api :as dc]
|
||||
;; [clj-time.core :as time]
|
||||
;; [clj-time.coerce :as coerce]
|
||||
)
|
||||
(:import [java.util UUID]))
|
||||
|
||||
|
||||
@@ -9,11 +12,11 @@
|
||||
(defn -by
|
||||
[f fv xs]
|
||||
(reduce
|
||||
#(assoc %1 (f %2) (fv %2))
|
||||
{}
|
||||
xs))
|
||||
#(assoc %1 (f %2) (fv %2))
|
||||
{}
|
||||
xs))
|
||||
|
||||
(defn -pull-many [db read ids ]
|
||||
(defn -pull-many [db read ids]
|
||||
(->> (dc/q '[:find (pull ?e r)
|
||||
:in $ [?e ...] r]
|
||||
db
|
||||
@@ -21,82 +24,93 @@
|
||||
read)
|
||||
(map first)))
|
||||
|
||||
;; TODO add DATOMIC_EXT_CLASSPATH ala https://docs.datomic.com/pro/reference/database-functions.html#transaction-functions
|
||||
;; (defn transform-common [v]
|
||||
;; (cond
|
||||
;; (nil? v)
|
||||
;; v
|
||||
|
||||
;; (satisfies? clj-time.core/DateTimeProtocol v)
|
||||
;; (clj-time.coerce/to-date v)
|
||||
|
||||
;; :else
|
||||
;; v))
|
||||
|
||||
|
||||
(defn upsert-entity [db entity]
|
||||
(when-not (or (:db/id entity)
|
||||
(:db/ident entity))
|
||||
(datomic.api/cancel {:cognitect.anomalies/category :cognitect.anomalies/incorrect
|
||||
:cognitect.anomalies/message
|
||||
(str "Cannot upsert without :db/id or :db/ident, " entity)}))
|
||||
(:db/ident entity))
|
||||
(datomic.api/cancel {:cognitect.anomalies/category :cognitect.anomalies/incorrect
|
||||
:cognitect.anomalies/message
|
||||
(str "Cannot upsert without :db/id or :db/ident, " entity)}))
|
||||
(let [e (or (:db/id entity) (:db/ident entity))
|
||||
is-new? (string? e)
|
||||
extant-entity (when-not is-new?
|
||||
(dc/pull db (keys entity) (or (:db/id entity) (:db/ident entity))))
|
||||
ident->value-type (-by :db/ident (comp :db/ident
|
||||
:db/valueType)
|
||||
(-pull-many
|
||||
:db/valueType)
|
||||
(-pull-many
|
||||
db
|
||||
[{:db/valueType [:db/ident]} :db/ident]
|
||||
(keys entity)))
|
||||
|
||||
ident->cardinality (-by :db/ident (comp :db/ident
|
||||
:db/cardinality)
|
||||
(-pull-many
|
||||
:db/cardinality)
|
||||
(-pull-many
|
||||
db
|
||||
[{:db/cardinality [:db/ident]} :db/ident]
|
||||
(keys entity)))
|
||||
ops (->> entity
|
||||
(reduce
|
||||
(fn [ops [a v]]
|
||||
(cond
|
||||
(= :db/id a)
|
||||
ops
|
||||
(fn [ops [a v]]
|
||||
(cond
|
||||
(= :db/id a)
|
||||
ops
|
||||
|
||||
(= :db/ident a)
|
||||
ops
|
||||
(= :db/ident a)
|
||||
ops
|
||||
|
||||
(or (= v (a extant-entity))
|
||||
(= v (:db/ident (a extant-entity) :nope))
|
||||
(= v (:db/id (a extant-entity)) :nope))
|
||||
ops
|
||||
|
||||
(and (nil? v)
|
||||
(not (nil? (a extant-entity))))
|
||||
(if (= :db.cardinality/many (ident->cardinality a))
|
||||
(into ops (map (fn [v]
|
||||
[:db/retract e a (cond-> v
|
||||
(:db/id v) :db/id)])
|
||||
(a extant-entity)))
|
||||
(or (= v (a extant-entity))
|
||||
(= v (:db/ident (a extant-entity) :nope))
|
||||
(= v (:db/id (a extant-entity)) :nope))
|
||||
ops
|
||||
|
||||
(conj ops [:db/retract e a (cond-> (a extant-entity)
|
||||
(:db/id (a extant-entity)) :db/id)]))
|
||||
(and (nil? v)
|
||||
(not (nil? (a extant-entity))))
|
||||
(if (= :db.cardinality/many (ident->cardinality a))
|
||||
(into ops (map (fn [v]
|
||||
[:db/retract e a (cond-> v
|
||||
(:db/id v) :db/id)])
|
||||
(a extant-entity)))
|
||||
|
||||
(nil? v)
|
||||
ops
|
||||
(conj ops [:db/retract e a (cond-> (a extant-entity)
|
||||
(:db/id (a extant-entity)) :db/id)]))
|
||||
|
||||
(nil? v)
|
||||
ops
|
||||
|
||||
;; reset relationships if it's refs, and not a lookup (i.e., seq of maps, or empty seq)
|
||||
|
||||
(and (sequential? v) (= :db.type/tuple (ident->value-type a)) (not (= :db.cardinality/many (ident->cardinality a))))
|
||||
(conj ops [:db/add e a v])
|
||||
|
||||
(and (sequential? v) (= :db.type/tuple (ident->value-type a)) (not (= :db.cardinality/many (ident->cardinality a))))
|
||||
(conj ops [:db/add e a v])
|
||||
(and (sequential? v) (= :db.type/ref (ident->value-type a)) (every? map? v))
|
||||
(into ops [[:reset-rels e a v]])
|
||||
|
||||
(and (sequential? v) (= :db.type/ref (ident->value-type a)) (every? map? v))
|
||||
(into ops [[:reset-rels e a v]])
|
||||
(= :db.cardinality/many (ident->cardinality a))
|
||||
(into ops [[:reset-scalars e a v]])
|
||||
|
||||
(= :db.cardinality/many (ident->cardinality a))
|
||||
(into ops [[:reset-scalars e a v]])
|
||||
(and (sequential? v) (not= :db.type/ref (ident->value-type a)))
|
||||
(into ops [[:reset-scalars e a v]])
|
||||
|
||||
(and (sequential? v) (not= :db.type/ref (ident->value-type a)))
|
||||
(into ops [[:reset-scalars e a v]])
|
||||
(and (map? v)
|
||||
(= :db.type/ref (ident->value-type a)))
|
||||
(let [id (or (:db/id v) (-random-tempid))]
|
||||
(-> ops
|
||||
(conj [:db/add e a id])
|
||||
(into [[:upsert-entity (assoc v :db/id id)]])))
|
||||
|
||||
(and (map? v)
|
||||
(= :db.type/ref (ident->value-type a)))
|
||||
(let [id (or (:db/id v) (-random-tempid))]
|
||||
(-> ops
|
||||
(conj [:db/add e a id])
|
||||
(into [[:upsert-entity (assoc v :db/id id)]])))
|
||||
|
||||
:else
|
||||
(conj ops [:db/add e a v])
|
||||
))
|
||||
[]))]
|
||||
:else
|
||||
(conj ops [:db/add e a v])))
|
||||
[]))]
|
||||
ops))
|
||||
|
||||
Reference in New Issue
Block a user