Files
nothoughts/src/cljs/emptyhead/idea/crud.cljs
2024-10-08 11:47:30 +02:00

60 lines
2.0 KiB
Clojure

(ns emptyhead.idea.crud
"Functions for Creating, Updating and Deleting ideas.
The 'R' in 'CRUD' is implemented by [[emptyhead.idea.protocol/value]]."
(:require [emptyhead.idea.state :refer [state]]
[emptyhead.idea.property :as prop]
[emptyhead.idea.protocol :as prtc]))
(defn- register-idea!
"Helper function to scaffold an 'empty' idea."
[ref]
(swap! state assoc-in [ref :_meta :_properties] #{})
(swap! state assoc-in [ref :_meta :_reference] ref)
ref)
(defn swap-idea!
"Swap data inside `idea` with given `data`.
Returns a reference to `idea`."
[idea data]
(swap! state assoc
(prtc/reference idea)
(merge data {:_meta (prtc/val-fn :_meta idea)}))
(prtc/reference idea))
(defn extend-idea!
"Merge `data` into state of `idea`.
Returns a reference to `idea`."
[idea data]
(swap! state assoc (prtc/reference idea) (prtc/val-fn merge idea data))
(prtc/reference idea))
(defn mutate-idea!
"Evaluate `fun` on `idea` with optional extra `args`, then replace `idea` by the result.
Returns a reference to `idea`."
[fun idea & args]
(swap-idea! idea (prtc/val-fn fun idea args))
(prtc/reference idea))
(defn forget-idea!
"Delete `idea` from the state.
Returns a copy of the `idea`."
[idea]
(let [val (prtc/value idea)]
(apply prop/remove-property! idea (prop/properties idea))
(prtc/ref-fn #(swap! state dissoc %) idea)
(prtc/copy val)))
(defn have-idea!
"Instantiate up to `count` new ideas, optionally prefixing reference symbol with `prefix`.
Additionally allows you to immediately attach `properties` and `data`.
Returns a single idea or a list of ideas depending on whether `count` was given."
[& {:keys [prefix count properties data]
:or {count 1 prefix "idea_" properties []}}]
(let [fun #(register-idea! (gensym prefix))
ideas (take count (repeatedly fun))]
(run! #(apply prop/register-property! % properties) ideas)
(when data (run! #(extend-idea! % data) ideas))
(if (= count 1)
(first ideas)
ideas)))