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

Doc update fx #40

Draft
wants to merge 22 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
4dec6f3
:firebase/transaction and :firebase/swap
benzenwen Mar 17, 2019
1df3bab
0.9.1-SNAPSHOT e msft
Peteypete Oct 12, 2019
7fb967d
microsoft login
Peteypete Oct 12, 2019
466f47b
MVP for Firebase Storage (NB. different than Firestore)
benzenwen Dec 8, 2020
25c2cfe
return nil instead of empty vector when no values are available or on
murtaza52 Feb 9, 2021
0037abc
Merge pull request #1 from benzenwen/513-coa-account-numbers
benzenwen Feb 9, 2021
159a5fd
upgrade firebase dep
murtaza52 Mar 30, 2021
432dac1
Added firebase storeage delete fx
janetacarr Dec 2, 2022
bd60d55
Added delete from storage fx
janetacarr Dec 5, 2022
109c79c
project.clj: prefix tallyfor name - issue #2
Dec 14, 2022
fa2c156
Merge pull request #3 from tallyfor/2-pull-request-tweak-project-name…
jojoucsd Dec 26, 2022
764d5d7
project.clj: bump version to v0.10.1
Dec 26, 2022
71624dd
Merge pull request #5 from tallyfor/4-bump-version-to-0.10.1
jojoucsd Dec 27, 2022
1fbe1e3
.github/workflows/cd.yml: add Continuous Deployment
Jan 10, 2023
e70bd2e
project.clj: tweak project definition for CD procedure
Jan 10, 2023
a716301
Merge pull request #7 from tallyfor/6-add-continuous-deployment-for-t…
benzenwen Jan 11, 2023
529c04c
Invoke on-failure for exception thrown in transaction
nodename Jul 5, 2023
f30050c
project.clj: bump version to 0.10.2
Jul 15, 2023
202816a
Merge pull request #9 from tallyfor/v0.10.2
pdelfino Jul 15, 2023
3aabe9b
project.clj: upgrade to 0.10.3 and completely remove lein-tools-deps
Jul 24, 2023
0af45ac
Merge pull request #12 from tallyfor/11-fix-0.10.02-lein-plugin-problem
jojoucsd Oct 13, 2023
57a32f9
Add detail for second level children for :firebase/update, i.e. use s…
benzenwen Mar 18, 2024
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
95 changes: 95 additions & 0 deletions .github/workflows/cd.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
name: 'cd'

on:
workflow_dispatch:
push:
branches:
- master
paths:
- 'project.clj'

permissions:
contents: read
# Needed for the 'trilom/file-changes-action' action
pull-requests: read

# This allows a subsequently queued workflow run to interrupt previous runs
concurrency:
group: '${{ github.workflow }} @ ${{ github.event.pull_request.head.label || github.head_ref || github.ref }}'
cancel-in-progress: true

jobs:
build:
runs-on: ${{ fromJSON('["ubuntu-latest", "self-hosted"]')[github.repository == 'github/docs-internal'] }}
steps:

- name: Checkout
uses: actions/checkout@v3
with:
ref: ${{ github.event.pull_request.head.sha }}

- name: Setup java
uses: actions/setup-java@v3
with:
distribution: 'zulu' # See 'Supported distributions' for available options
java-version: '11'

- name: Display (print) node and java versions
run:
node -v && java --version

- name: Install clojure tools
uses: DeLaGuardo/[email protected]
with:
# Install just one or all simultaneously
# The value must indicate a particular version of the tool, or use 'latest'
# to always provision the latest version
cli: 1.11.1.1149 # Clojure CLI based on tools.deps
lein: 2.9.8 # Leiningen
clj-kondo: 2022.05.31 # Clj-kondo

- name: Get clj-kondo version. Clj-kondo searches for opportunities of optimizations
run: clj-kondo --version

# # Optional step:
# - name: Cache clojure dependencies
# uses: actions/cache@v3
# with:
# path: |
# ~/.m2/repository
# ~/.gitlibs
# ~/.deps.clj
# # List all files containing dependencies:
# key: cljdeps-${{ hashFiles('deps.edn') }}
# # key: cljdeps-${{ hashFiles('deps.edn', 'bb.edn') }}
# # key: cljdeps-${{ hashFiles('project.clj') }}
# # key: cljdeps-${{ hashFiles('build.boot') }}
# restore-keys: cljdeps-

- name: Test if vanilla clojure code is working
run: clojure -e "(+ 1 1)"

- name: Display Leiningen version
run: lein -v

# - name: Run cljfmt formatter
# run: lein cljfmt check

# - name: Run clj-kondo
# run: clj-kondo --lint src

- name: lein install on this version of firebase-re-frame
run:
lein install

# - name: Run lein tests
# run: lein test

- name: Deploy to Github Package Registry
env:
GITHUB_TOKEN: ${{ secrets.RE_FRAME_FIREBASE_REPOSITORY_SECRET_ACTIONS }}
run: |
mkdir -p ~/.m2
echo "<settings><servers><server><id>github</id><username>$(echo '$GITHUB_REPOSITORY' | awk -F / '{print $1}')</username><password>\${env.GITHUB_TOKEN}</password></server></servers></settings>" > ~/.m2/settings.xml
REPO="gh::default::https://maven.pkg.github.com/${GITHUB_REPOSITORY}"
mvn deploy -DaltReleaseDeploymentRepository="${REPO}" -DaltSnapshotDeploymentRepository="${REPO}"
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,6 @@ checkouts/
pom.xml

.firebaserc

# MacOS system file
.DS_Store
68 changes: 62 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -261,15 +261,18 @@ See [Firebase docs][phone-auth] for details.

The firebase database is a tree. You can write values to nodes in a tree, or push them
to auto-generated unique sub-nodes of a node. In re-frame-firebase, these are exposed
through the `:firebase/write` `:firebase/push` and `:firebase/update` effect handlers.
through the `:firebase/write` and `:firebase/push` effect handlers.

Each takes parameters:
- `:path` - A vector representing a node in the firebase tree, e.g. `[:my :node]`
- `:value` - The value to write or push.
- `:on-success` - Event vector or function to call when write succeeds.
- `:on-failure` - Event vector or function to call with the error.

Example:
There are also the atomic `:firebase/update`, `:firebase/transaction`, and
`:firebase/swap` effect handlers, discussed below.

Write example:

```clojure
(re-frame/reg-event-fx
Expand Down Expand Up @@ -299,15 +302,19 @@ Example (diff in bold):
> **Note:** Events will also receive the same creation key. `(rf/reg-event-fx :event-name (fn [ctx [_ key]])`


`:firebase/update` can write to children subnodes, without overwriting children's siblings. Use
`:firebase/update` can write to children and decendant subnodes, without overwriting siblings. Use
a clojure map of children subnode(s) and their value(s). `:firebase/write` overwrites all children.

NB: to update second or deeper level decendants without disturbing siblings, use a
string-delimited-with-slash (/) key. See the "universe/subuniverse"
example below.

Example (diff in bold):

<pre>
(re-frame/reg-event-fx
:update-status
(fn [{db :db} [_ <b>status-children</b>]] ;; status-children is e.g. {:life 42, :universe 42, :everything 42}
(fn [{db :db} [_ <b>status-children</b>]] ;; status-children is e.g. {:life 42, "universe/subuniverse" 42, :everything 42}
{:firebase/<b>update</b> {:path [:status]
:value <b>status-children</b>
:on-success #(js/console.log <b>"Updated status-children"</b>)
Expand All @@ -318,8 +325,57 @@ Example (diff in bold):

[multi-location-update-blogpost]: https://firebase.googleblog.com/2015/09/introducing-multi-location-updates-and_86.html

Re-frame-firebase also supplies `:firebase/multi` to allow multiple write and/or
pushes from a single event:
The `:firebase/transaction` effect handler and its more Clojure-y variant
`:firebase/swap` perform atomic modifications to the tree.

In `:firebase/transaction`, the `:transaction-update` parameter is a function that takes
one parameter that is the old value at the `:path` location and returns the new
value. Note that the function may be called multiple times, so should be free of side
effects.

The function must also tolerate a `nil` input gracefully. To abort a transaction, say to
avoid overwriting an existing value, the function returns `js/undefined`.

Finally, note that the `:apply-locally` boolean indicates whether the local
firebase-system cached value should be applied optimistically, which may result in more
than one update event to be emitted if the function needs to be run more than once. The
default value is `true`.

```clojure
{:firebase/transaction {:path [:my :data]
:transaction-update (fn [old-val] (if old-val (inc old-val)))
:apply-locally false ;; default is true = multiple update events may be received if transaction-update needs to be run more than once.
;; The on-* handlers can also take a re-frame event
:on-success (fn [snapshot committed] (if committed (prn "Transaction committed: " snapshot)))
:on-failure (fn [err snapshot committed] (prn "Error: " err))}}
```

`:firebase/swap` is similar to `:firebase/transaction` but takes an `:argv` argument,
typically a vector. The argument `:f` is the renamed `:transaction-update`, the
update function. The old value at the `:path` is prepended to `:argv` and then `:f`
is applied much like `clojure.core\swap!` does for atoms.

Both atomic effect handlers are provided to appeal to users coming from Firebase-first
or Clojure-first backgrounds, respectively. For those coming from Firebase, note that
the `snapshot` and `committed` parameters are reversed in on-*. This is to facilitate
re-frame event handlers as they receive only the first passed parameter, ignoring the
rest. Passing snapshot rather than committed makes for more useful possibilities.

Example (diff in bold):

<pre>
{:firebase/<b>swap</b> {:path [:my :data]
<b>:f + </b>
<b>:argv [2 3] ;; So the swap will perform (+ old-value 2 3) </b>
:apply-locally false ;; default is true = multiple update events may be received if transaction-update needs to be run more than once.
;; The on-* handlers can also take a re-frame event
:on-success (fn [snapshot committed] (if committed (prn "Transaction committed: " snapshot)))
<b>:on-failure [:handle-failure]</b>}}
</pre>


Re-frame-firebase also supplies `:firebase/multi` to allow multiple writes and other
effects from a single event:

```clojure
(re-frame/reg-event-fx
Expand Down
28 changes: 25 additions & 3 deletions project.clj
Original file line number Diff line number Diff line change
@@ -1,20 +1,42 @@
;;; Author: David Goldfarb ([email protected])
;;; Copyright (c) 2017-8, David Goldfarb

(defproject com.degel/re-frame-firebase "0.9.0-SNAPSHOT"
(defproject tallyfor/re-frame-firebase "0.10.3"
:description "A re-frame wrapper around firebase"
: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"]
[cljsjs/firebase "7.5.0-0"] ;;"5.7.3-1"
[re-frame "0.10.6"]
[com.degel/iron "0.4.0"]]
[com.degel/iron "0.4.0"]
[lein-pprint "1.3.2"]
[lein-cljsbuild "1.1.8"]
[lein-bump-version "0.1.6"]]
;; run lein install with LEIN_SNAPSHOTS_IN_RELEASE=true lein install
:lein-tools-deps/config {:config-files [:install :user :project]}

:jvm-opts ^:replace ["-Xmx1g" "-server"]
:cljsbuild {:builds {}} ; prevent https://github.com/emezeske/lein-cljsbuild/issues/413
:plugins [[lein-npm "0.6.2"]]
:npm {:dependencies [[source-map-support "0.5.6"]]}
:profiles {:dev {:dependencies [[clj-stacktrace "0.2.8"]
[binaryage/devtools "0.9.10"]
[org.clojure/tools.namespace "1.1.0"]]}}
:source-paths ["src" "target/classes"]
;; Change your environment variables (maybe editing .zshrc or .bashrc) to have:
;; export LEIN_USERNAME="pdelfino"
;; export LEIN_PASSWORD="your-personal-access-token-the-same-used-on-.npmrc"
;; LEIN_PASSWORD should use the same Token used by .npmrc
;; Also, do "LEIN_SNAPSHOTS_IN_RELEASE=true lein install" or edit your .zshrc:
;; export LEIN_SNAPSHOTS_IN_RELEASE=true
:repositories {"releases" {:url "https://maven.pkg.github.com/tallyfor/*"
:username :env/LEIN_USERNAME ;; change your env
:password :env/LEIN_PASSWORD}}

:pom-addition [:distribution-management [:repository [:id "github"]
[:name "GitHub Packages"]
[:url "https://maven.pkg.github.com/tallyfor/re-frame-firebase"]]]
:clean-targets ["out" "release"]
:target-path "target")
41 changes: 36 additions & 5 deletions src/com/degel/re_frame_firebase.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@
[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]))

;;; Write a value to Firebase.
;;; See https://firebase.google.com/docs/reference/js/firebase.database.Reference#set
Expand All @@ -35,6 +36,28 @@
;;;
(re-frame/reg-fx :firebase/update database/update-effect)

;;; Transactionally reads and writes a value to Firebase. NB: :transaction-update function
;;; may run more than once so must be free of side effects. Importantly, it must be able
;;; to handle null data. To abort a transaction, return js/undefined.
;;; See https://firebase.google.com/docs/reference/js/firebase.database.Reference#transaction
;;;
;;; Examples FX:
;;; {:firebase/transaction {:path [:my :data]
;;; :transaction-update (fn [old-val] (if old-val (inc old-val)))
;;; :apply-locally false ;; default is true = multiple update events may be received if transaction-update needs to be run more than once.
;;; ;; The on-* handlers can also take a re-frame event
;;; :on-success (fn [snapshot committed] (if committed (prn "Transaction committed: " snapshot)))
;;; :on-failure (fn [err snapshot committed] (prn "Error: " err))}}
;;;
;;; {:firebase/swap {:path [:my :data]
;;; :f +
;;; :argv [2 3]
;;; :apply-locally false ;; default is true = multiple update events may be received if transaction-update needs to be run more than once.
;;; ;; The on-* handlers can also take a re-frame event
;;; :on-success (fn [snapshot committed] (if committed (prn "Transaction committed: " snapshot)))
;;; :on-failure [:firebase-error]}}
(re-frame/reg-fx :firebase/transaction database/transaction-effect)
(re-frame/reg-fx :firebase/swap database/swap-effect) ; A synonym with :argv for update function :f

;;; Write a value to a Firebase list.
;;; See https://firebase.google.com/docs/reference/js/firebase.database.Reference#push
Expand Down Expand Up @@ -74,6 +97,8 @@
:firebase/write (database/write-effect args)
:firebase/update (database/update-effect args)
:firebase/push (database/push-effect args)
:firebase/transaction (database/transaction-effect args)
:firebase/swap (database/swap-effect args)
:firebase/read-once (database/once-effect args)
:firestore/delete (firestore/delete-effect args)
:firestore/set (firestore/set-effect args)
Expand Down Expand Up @@ -120,10 +145,11 @@
;;; "https://www.googleapis.com/auth/calendar.readonly"]
;;; :custom-parameters {"login_hint" "[email protected]"}}}
;;;
(re-frame/reg-fx :firebase/google-sign-in auth/google-sign-in)
(re-frame/reg-fx :firebase/facebook-sign-in auth/facebook-sign-in)
(re-frame/reg-fx :firebase/twitter-sign-in auth/twitter-sign-in)
(re-frame/reg-fx :firebase/github-sign-in auth/github-sign-in)
(re-frame/reg-fx :firebase/google-sign-in auth/google-sign-in)
(re-frame/reg-fx :firebase/facebook-sign-in auth/facebook-sign-in)
(re-frame/reg-fx :firebase/twitter-sign-in auth/twitter-sign-in)
(re-frame/reg-fx :firebase/github-sign-in auth/github-sign-in)
(re-frame/reg-fx :firebase/microsoft-sign-in auth/microsoft-sign-in)


;;; Login to firebase using email/password authentication
Expand Down Expand Up @@ -360,6 +386,11 @@
;;;
(re-frame/reg-sub-raw :firestore/on-snapshot firestore/on-snapshot-sub)

;;; Firebase Storage, an online object store, different from the similarly named Firestore.

(re-frame/reg-fx :storage/put storage/put-effect)
(re-frame/reg-fx :storage/delete storage/delete-effect)


;;; Start library and register callbacks.
;;;
Expand Down
7 changes: 6 additions & 1 deletion src/com/degel/re_frame_firebase/auth.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,6 @@
(>evt [(core/default-error-handler)
(js/Error. (str "Unsupported sign-in-method: " sign-in-method ". Either :redirect or :popup are supported."))]))))


(defn google-sign-in
[opts]
;; TODO: use Credential for mobile.
Expand All @@ -97,6 +96,12 @@
(oauth-sign-in (js/firebase.auth.GithubAuthProvider.) opts))


(defn microsoft-sign-in
[opts]
(oauth-sign-in (js/firebase.auth.OAuthProvider. "microsoft.com") opts))



(defn email-sign-in [{:keys [email password]}]
(-> (js/firebase.auth)
(.signInWithEmailAndPassword email password)
Expand Down
Loading