Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pre post cleanup callbacks #22

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,18 @@ committed). It can be modified with the `storage-delay` atom or the
```


It's possible to modify the contents of the atom on the way into storage
and back out again using the optional arguments `pre-clean-fn` and
`post-clean-fn`.

* `pre-clean-fn` takes a single argument which is the value on the way
to being saved.
* `post-clean-fn` takes two arguments. The first is the value as it
comes out of storage. The second is the previous value (if any). You
can use this to merge the existing state with the state coming out of
storage.


[enduro](https://github.com/alandipert/enduro) is a Clojure library
that provides similar functionality by using files or a database for
storage.
Expand Down
36 changes: 18 additions & 18 deletions src/alandipert/storage_atom.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,14 @@
(-get [this not-found])
(-commit! [this value] "Commit value to storage at location."))

(deftype StorageBackend [store key]
(deftype StorageBackend [store key pre-clean-fn post-clean-fn]
IStorageBackend
(-get [this not-found]
(-get [_this not-found]
(if-let [existing (.getItem store (clj->json key))]
(json->clj existing)
((or post-clean-fn identity) (json->clj existing) nil)
not-found))
(-commit! [this value]
(.setItem store (clj->json key) (clj->json value))))
(-commit! [_this value]
(.setItem store (clj->json key) (clj->json ((or pre-clean-fn identity) value)))))


(defn debounce-factory
Expand Down Expand Up @@ -66,7 +66,7 @@ discarded an only the new one is committed."
@storage-delay)))))))

(defn maybe-update-backend
[atom storage k default e]
[atom storage k default post-clean-fn e]
(when (identical? storage (.-storageArea e))
(if (empty? (.-key e)) ;; is all storage is being cleared?
(binding [*watch-active* false]
Expand All @@ -77,15 +77,15 @@ discarded an only the new one is committed."
(binding [*watch-active* false]
(reset! atom (let [value (.-newValue e)] ;; new value, or is key being removed?
(if-not (string/blank? value)
(json->clj value)
((or post-clean-fn identity) (json->clj value) @atom)
default))))))
(catch :default e)))))
(catch :default _e)))))

(defn link-storage
[atom storage k]
[atom storage k post-clean-fn]
(let [default @atom]
(.addEventListener js/window "storage"
#(maybe-update-backend atom storage k default %))))
#(maybe-update-backend atom storage k default post-clean-fn %))))

(defn dispatch-remove-event!
"Create and dispatch a synthetic StorageEvent. Expects key to be a string.
Expand All @@ -102,7 +102,7 @@ discarded an only the new one is committed."

(defn load-html-storage
[storage k]
(-get (StorageBackend. storage k) nil))
(-get (StorageBackend. storage k nil nil) nil))

(defn load-local-storage [k]
(load-html-storage js/localStorage k))
Expand All @@ -113,17 +113,17 @@ discarded an only the new one is committed."
;;; main API

(defn html-storage
[atom storage k]
(link-storage atom storage k)
(store atom (StorageBackend. storage k)))
[atom storage k pre-clean-fn post-clean-fn]
(link-storage atom storage k post-clean-fn)
(store atom (StorageBackend. storage k pre-clean-fn post-clean-fn)))

(defn local-storage
[atom k]
(html-storage atom js/localStorage k))
[atom k & [pre-clean-fn post-clean-fn]]
(html-storage atom js/localStorage k pre-clean-fn post-clean-fn))

(defn session-storage
[atom k]
(html-storage atom js/sessionStorage k))
[atom k & [pre-clean-fn post-clean-fn]]
(html-storage atom js/sessionStorage k pre-clean-fn post-clean-fn))

;; Methods to safely remove items from storage or clear storage entirely.

Expand Down