Build Status Latest version Gitter chat License: MIT

Overview

Firebase4s aims to provide a Scala-friendly alternative to the Firebase Java SDK. By providing more idiomatic API interfaces and automatically handling Scala-to-Java data conversions, Firebase4s eliminates much of the boilerplate required to use the Java SDK. Firebase4s currently provides the same Realtime Database and Authentication features as the Java SDK and aims to provide all of the same functionality over time.


Getting Started

To use firebase4s in your project, add the following to your build.sbt:

libraryDependencies += "com.github.firebase4s" %% "firebase4s" % "0.0.4"

Initialize

Initialize the App with your Firebase service account credentials and database url, which may be obtained from the Firebase console.

import com.firebase4s.App

val serviceAccount = getClass.getResourceAsStream("/serviceAccountCredentials.json")

App.initialize(serviceAccount, "https://<MY_INSTANCE>.firebaseio.com")

The above code snippet assumes that your Firebase service account credentials exist in your project's resources directory.

Realtime Database

To get an instance of a DatabaseReference:

import com.firebase4s.database.Database

val db: Database = Database.getInstance()
val fooRef: DatabaseReference = db.ref("foo")

There are five categories of supported data types:

    Simple Types: String, Boolean, Int, Long, Double
    Maps containing Simple Types: Map[String, String], Map[String, Boolean], etc.
    Iterables containing Simple Types: List[String] , Vector[Long], etc.
    Options of any of the above: Option[Int], Option[List[String]], etc.
    Classes

Currently, only JavaBean classes are supported. However, Firebase4s offers a toMap helper method which makes working with non-nested case classes easier. Future versions of Firebase4s will fully support the use of case classes through the use of Scala Macro Annotations. and/or Shapeless

Examples:

Set and retrieve a List[Int]:

/** Get a database reference */
val listRef: DatabaseReference = db.ref("myList")

/** Set value at reference location */
val result: Future[List[Int]] = liftRef.set(List(1, 2, 3))

/** Get value at ref location */
ref.get()
  .map(snapshot => snapshot.getValue)
  .map((list: Option[List[Int]]) => ???) // handle result

Set and retrieve a User:

import scala.beans.BeanProperty

/** JavaBean Class Constructor */
class User() {
  @BeanProperty var name: String = _
  @BeanProperty var email: String = _
}

/** Get a database reference */
val userRef = db.ref("user")

/** Create user */
val user = new User()
user.name = "timothy"
user.email = "[email protected]"

/** Set user at ref location */
userRef.set(user).foreach(println) // User("timothy","[email protected]")

/** Get user at ref location */
userRef.get()
  .map(snapshot => snapshot.getValue(classOf[User]))
  .map((user: Option[UserRecord]) => ???) // handle result

Working with case classes:

/**
  * The Helpers module provides a `toMap` method which
  * we can invoke on our case class to convert it to a
  * Map[String, Any] that can be set as a value in the
  * in the database.  When retrieving the value as this
  * ref location, we will get back a Map[String, Any]
  * representation of our case class instance.
  */

import com.firebase4s.database.Helpers._

case class User(name: String, age: Int)

val user = User("tim", 44)
val userRef = db.ref("user")

userRef.set(user.toMap)

userRef.get().foreach(snapshot => {
  println(snapshot.getValue) // Map(name -> tim, age -> 44)
})

Authentication

Create a User:
import com.firebase4s.{Auth, UserCreationProps}

val auth: Auth = Auth.getInstance()

// User Props
val props = UserCreationProps(
  email = Some("[email protected]"),
  displayName = Some("tim"),
  phoneNumber = Some("+1555555555"),
  photoUrl = Some("http://testing.com/photo.jpeg")
)

auth.createUser(props)
  .map((user: UserRecord) => ???) // handle results
Update a User:
import com.firebase4s.{Auth, UserUpdateProps}

val auth: Auth = Auth.getInstance()

// Props to update
val props = UserUpdateProps(
  email = Some("[email protected]"),
  phoneNumber = Some("+15655655555")
)

auth.updateUser(props)
  .map((user: UserRecord) => ???) // handle results
Delete a User:
auth.deleteUser(user.uid)
  .map(uid => ???) // handle result
Verify a Firebase ID Token:
auth.verifyIdToken(token)
  .map((token: FirebaseToken) => token.uid)
  .map(userId => ???)
Create a Custom Token:
val extraClaims = Map("admin" -> true)
auth.createCustomToken(uid, Some(extraClaims)))
  .map(token => ???]) // Provide token to client