Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
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
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
.lein-deps-sum
.lein-plugins/
.lein-repl-history
.clj-kondo
.lsp
.repl*
/*.iml
/.cljs_node_repl/
Expand Down
91 changes: 91 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -528,6 +528,97 @@ as it is meant to be used as a subscription.
```


### Storage

[Storage](https://firebase.google.com/docs/storage) Cloud Storage for Firebase is a powerful, simple, and cost-effective object storage service.
It uses effects for put, delete, download operations.

#### Put
Puts a collection of File objects into a Firebase Storage bucket.
See: https://firebase.google.com/docs/storage/web/upload-files

Required arguments :path :file

- :path Path to object in the Storage bucket
- :file File (https://developer.mozilla.org/en-US/docs/Web/API/File)
- :bucket If not supplied, will assume the default Firebase allocated bucket
- :metadata Map of metadata to set on Storage object
- :on-progress Will be provided with the percentage complete
- :on-success
- :on-error

Example FX:
```clojure
{:storage/put [{:path "path/to/object"
:file File
:metadata {:customMetadata {"some-key" "some-value"}}
:on-progress #(.log js/console (str "Upload is " % "% complete."))
:on-success #(js/alert "Success!")
:on-error #(js/alert "Error: " %)}]}
```

#### Delete
Deletes a collection of object paths/keys from a Firebase Storage bucket.
See: https://firebase.google.com/docs/storage/web/delete-files

Required arguments :path

- :path Path to object in the Storage bucket
- :bucket If not supplied, will assume the default Firebase allocated bucket
- :on-success
- :on-error

Example FX:
```clojure
{:storage/delete [{:path "path/to/object"
:on-success #(js/alert "Success!")
:on-error #(js/alert "Error: " %)}]}
```


#### Download URL
Generates a url with which the browser can download an object from Firebase Storage
See: https://firebase.google.com/docs/storage/web/download-files

Required arguments: :path

- :path Path to object in the Storage bucket
- :bucket If not supplied, will assume the default Firebase allocated bucket
- :on-success Will be provided with the download url
- :on-error

Example FX:
```clojure
{:storage/download-url {:path "path/to/object"
:on-success #(js/window.open %)
:on-error #(js/alert "Error: " %)}}
```


### Functions

[Functions](https://firebase.google.com/docs/functions) Cloud Functions for Firebase is a serverless framework that lets you automatically run backend code in response to events.
It uses effects for call.

#### Call
Executes a Callable Firebase Cloud Function
See: https://firebase.google.com/docs/functions/callable

Required arguments: :cfn-name :data
- :cfn-name Cloud Function name
- :data Map containing request data
- :on-success Will be called with a clojure Map containing the response data
- :on-error

Example FX:
```clojure
{:functions/call {:cfn-name "my-function-name"
:data {:foo "bar"}
:on-success #(js/alert (:foobar %))
:on-error #(js/alert "Error: " %)}}
```


## Examples and projects

There are examples provided in the [examples](examples) folder. It is great to
Expand Down
10 changes: 5 additions & 5 deletions project.clj
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@
:url "https://github.com/deg/re-frame-firebase"
:license {:name "Eclipse Public License"
:url "http://www.eclipse.org/legal/epl-v10.html"}
:dependencies [[org.clojure/clojure "1.10.0"]
[org.clojure/clojurescript "1.10.439"]
[cljsjs/firebase "5.7.3-1"]
[re-frame "0.10.6"]
[com.degel/iron "0.4.0"]]
;; :dependencies [[org.clojure/clojure "1.10.0"]
;; [org.clojure/clojurescript "1.10.439"]
;; [cljsjs/firebase "5.7.3-1"]
;; [re-frame "0.10.6"]
;; [com.degel/iron "0.4.0"]]
:jvm-opts ^:replace ["-Xmx1g" "-server"]
:cljsbuild {:builds {}} ; prevent https://github.com/emezeske/lein-cljsbuild/issues/413
:plugins [[lein-npm "0.6.2"]]
Expand Down
161 changes: 157 additions & 4 deletions src/com/degel/re_frame_firebase.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,11 @@
[com.degel.re-frame-firebase.core :as core]
[com.degel.re-frame-firebase.auth :as auth]
[com.degel.re-frame-firebase.database :as database]
[com.degel.re-frame-firebase.firestore :as firestore]))
[com.degel.re-frame-firebase.firestore :as firestore]
[com.degel.re-frame-firebase.storage :as storage]
[com.degel.re-frame-firebase.functions :as functions]
[com.degel.re-frame-firebase.analytics :as analytics]
[com.degel.re-frame-firebase.app-check :as app-check]))

;;; Write a value to Firebase.
;;; See https://firebase.google.com/docs/reference/js/firebase.database.Reference#set
Expand Down Expand Up @@ -141,6 +145,50 @@
(re-frame/reg-fx :firebase/email-create-user auth/email-create-user)


;;; Updates the user's display name and profile photo URL
;;;
;;; Accepts a map with :profile :on-success :on-error
;;;
;;; Example FX:
;;; {:firebase/update-profile {:profile {:displayName "Joe Soap"
;;; :photoURL "http://my.photo.com"}
;;; :on-success #(js/alert "Success!")
;;; :on-error #(js/alert "Error!")}}
;;;
(re-frame/reg-fx :firebase/update-profile auth/update-profile)

;;; Updates the user's email address
;;;
;;; Accepts a map with :email :on-success :on-error
;;;
;;; Example FX:
;;; {:firebase/update-email {:email "joe@soap.com"
;;; :on-success #(js/alert "Success!")
;;; :on-error #(js/alert "Error!")}}
;;;
(re-frame/reg-fx :firebase/update-email auth/update-email)

;;; Send a user a verification email
;;;
;;; Accepts a map with :on-success :on-error
;;;
;;; Example FX:
;;; {:firebase/send-email-verification {:on-success #(js/alert "Success!")
;;; :on-error #(js/alert "Error!")}}
;;;
(re-frame/reg-fx :firebase/send-email-verification auth/send-email-verification)

;;; Applies a verification code sent to the user by email
;;;
;;; Accepts a map with :action-code :on-success :on-error
;;;
;;; Example FX:
;;; {:firebase/apply-action-code {:action-code "1234567"
;;; :on-success #(js/alert "Success!")
;;; :on-error #(js/alert "Error!")}}
;;;
(re-frame/reg-fx :firebase/apply-action-code auth/apply-action-code)

;;; Login to firebase anonymously
;;;
;;; Parameter is not used
Expand Down Expand Up @@ -361,6 +409,103 @@
(re-frame/reg-sub-raw :firestore/on-snapshot firestore/on-snapshot-sub)


;;; Puts a collection of File objects into a Firebase Storage bucket.
;;; See: https://firebase.google.com/docs/storage/web/upload-files
;;;
;;; Required arguments: :path :file
;;;
;;; - :path Path to object in the Storage bucket
;;; - :file File (https://developer.mozilla.org/en-US/docs/Web/API/File)
;;; - :bucket If not supplied, will assume the default Firebase allocated bucket
;;; - :metadata Map of metadata to set on Storage object
;;; - :on-progress Will be provided with the percentage complete
;;; - :on-success
;;; - :on-error
;;;
;;; Example FX:
;;; {:storage/put [{:path "path/to/object"
;;; :file File
;;; :metadata {:customMetadata {"some-key" "some-value"}}
;;; :on-progress #(.log js/console (str "Upload is " % "% complete."))
;;; :on-success #(js/alert "Success!")
;;; :on-error #(js/alert "Error: " %)}]}
;;;
(re-frame/reg-fx :storage/put storage/put-effect)


;;; Deletes a collection of object paths/keys from a Firebase Storage bucket.
;;; See: https://firebase.google.com/docs/storage/web/delete-files
;;;
;;; Required arguments: :path
;;;
;;; - :path Path to object in the Storage bucket
;;; - :bucket If not supplied, will assume the default Firebase allocated bucket
;;; - :on-success
;;; - :on-error
;;;
;;; Example FX:
;;; {:storage/delete [{:path "path/to/object"
;;; :on-success #(js/alert "Success!")
;;; :on-error #(js/alert "Error: " %)}]}
;;;
(re-frame/reg-fx :storage/delete storage/delete-effect)


;;; Generates a url with which the browser can download an object from Firebase Storage
;;; See: https://firebase.google.com/docs/storage/web/download-files
;;;
;;; Required arguments: :path
;;;
;;; - :path Path to object in the Storage bucket
;;; - :bucket If not supplied, will assume the default Firebase allocated bucket
;;; - :on-success Will be provided with the download url
;;; - :on-error
;;;
;;; Example FX:
;;; {:storage/download-url {:path "path/to/object"
;;; :on-success #(js/window.open %)
;;; :on-error #(js/alert "Error: " %)}}
;;;
(re-frame/reg-fx :storage/download-url storage/download-url-effect)


;;; Executes a Callable Firebase Cloud Function
;;; See: https://firebase.google.com/docs/functions/callable
;;;
;;; Required arguments: :cfn-name :data
;;;
;;; - :cfn-name Cloud Function name
;;; - :data Map containing request data
;;; - :on-success Will be called with a clojure Map containing the response data
;;; - :on-error
;;;
;;; Example FX:
;;; {:functions/call {:cfn-name "my-function-name"
;;; :data {:foo "bar"}
;;; :on-success #(js/alert (:foobar %))
;;; :on-error #(js/alert "Error: " %)}}
;;;
(re-frame/reg-fx :functions/call functions/call-effect)



;;; Logs an event in Firebase Analytics
;;; See: https://firebase.google.com/docs/analytics/events?authuser=0&platform=web
;;;
;;; Required arguments: :event :props
;;;
;;; - :event Name of the event (as keyword)
;;; - :props Map of key/value pairs of interesting information
;;;
;;; Example FX:
;;; {:analytics/log {:event :purchase-completed
;;; :props {:amount "123.45"
;;; :currency "USD"}}}
;;;
(re-frame/reg-fx :analytics/log analytics/log-effect)



;;; Start library and register callbacks.
;;;
;;;
Expand Down Expand Up @@ -394,12 +539,20 @@
;;;
(defn init [& {:keys [firebase-app-info
firestore-settings
app-check-settings
get-user-sub
set-user-event
default-error-handler]}]
default-error-handler
firebase-products]}]
(core/set-firebase-state :get-user-sub get-user-sub
:set-user-event set-user-event
:default-error-handler default-error-handler)
(core/initialize-app firebase-app-info)
(firestore/set-firestore-settings firestore-settings)
(auth/init-auth))
(when (firebase-products :firestore)
(firestore/set-firestore-settings firestore-settings))
(when (firebase-products :analytics)
(analytics/init))
(when (firebase-products :auth)
(auth/init-auth))
(when (firebase-products :app-check)
(app-check/init app-check-settings)))
17 changes: 17 additions & 0 deletions src/com/degel/re_frame_firebase/analytics.cljs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
(ns com.degel.re-frame-firebase.analytics
(:require
["@firebase/analytics" :refer (getAnalytics logEvent)]
[com.degel.re-frame-firebase.core :as core]))

(defn init
[]
(swap! core/firebase-state assoc
:analytics (-> @core/firebase-state
:app
getAnalytics)))

(defn log-effect
[{:keys [event props]} _]
(-> @core/firebase-state
:analytics
(logEvent (name event) (clj->js props))))
14 changes: 14 additions & 0 deletions src/com/degel/re_frame_firebase/app_check.cljs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
(ns com.degel.re-frame-firebase.app-check
(:require
["@firebase/app-check" :refer (initializeAppCheck ReCaptchaV3Provider)]
[com.degel.re-frame-firebase.core :as core]))

(defn init
[settings]
(when (:debug-provider settings)
(set! js/FIREBASE_APPCHECK_DEBUG_TOKEN true))
(swap! core/firebase-state assoc
:app-check (initializeAppCheck (:app @core/firebase-state)
(clj->js
{:provider (ReCaptchaV3Provider. (:site-key settings))
:isTokenAutoRefreshEnabled true}))))
Loading