All Projects β†’ ThomasWeiser β†’ Elmfire

ThomasWeiser / Elmfire

Licence: other
Firebase Bindings for Elm

Programming Languages

elm
856 projects

Labels

Projects that are alternatives of or similar to Elmfire

Todo Vue
Code for YouTube series on building a Todo App in Vue.js
Stars: ✭ 199 (-7.01%)
Mutual labels:  firebase
Geoflutterfire
πŸ”₯GeoFlutterFireπŸ”₯ is an open-source library that allows you to store and query firestore documents based on their geographic location.
Stars: ✭ 207 (-3.27%)
Mutual labels:  firebase
Qtfirebase
An effort to bring Google's Firebase C++ API to Qt + QML
Stars: ✭ 208 (-2.8%)
Mutual labels:  firebase
Angular Firebase Crud
Angular CRUD with Firebase using cloud firestore as a database, angular material and Bootstrap 4. Step by Step tutorial and working angular 7 example app.
Stars: ✭ 202 (-5.61%)
Mutual labels:  firebase
Firefly
Web app boilerplate for beginners based on Firebase and React πŸ”₯
Stars: ✭ 204 (-4.67%)
Mutual labels:  firebase
Fireadmin
Application for Managing Firebase Applications. Includes support for multiple environments and data migrations
Stars: ✭ 207 (-3.27%)
Mutual labels:  firebase
Godotfirebase
FireBase for godot
Stars: ✭ 199 (-7.01%)
Mutual labels:  firebase
Go Fcm
Firebase Cloud Messaging ( FCM ) Library using golang ( Go )
Stars: ✭ 212 (-0.93%)
Mutual labels:  firebase
Refire Forum
Serverless discussion forum built with React, Redux and Firebase
Stars: ✭ 206 (-3.74%)
Mutual labels:  firebase
Angularfire2 Offline
πŸ”Œ A simple wrapper for AngularFire2 to read and write to Firebase while offline, even after a complete refresh.
Stars: ✭ 209 (-2.34%)
Mutual labels:  firebase
Chat21 Android Sdk
Android Chat SDK built on Firebase
Stars: ✭ 204 (-4.67%)
Mutual labels:  firebase
Firebase Admin Dotnet
Firebase Admin .NET SDK
Stars: ✭ 201 (-6.07%)
Mutual labels:  firebase
Flatapp Firebase Flutter
Flap App with Firebase in Flutter by GeekyAnts.
Stars: ✭ 208 (-2.8%)
Mutual labels:  firebase
Nodejs Auth
Implementation of node.js authentication with social login ✌️, user impersonation πŸ’…, and no passport.js required πŸ’
Stars: ✭ 201 (-6.07%)
Mutual labels:  firebase
Remember
Capture, Edit and Save
Stars: ✭ 211 (-1.4%)
Mutual labels:  firebase
Expo Firebase Starter
πŸ”₯βš›οΈπŸ“± Expo + Firebase Starter Kit
Stars: ✭ 199 (-7.01%)
Mutual labels:  firebase
Buefy Shop
A sample shop built with Nuxt, Stripe, Firebase and Serverless Functions
Stars: ✭ 207 (-3.27%)
Mutual labels:  firebase
Taxi Booking App
This is a complete ride booking app, It uses google maps cordova plugin, firebase database and onesignal as notification provider.
Stars: ✭ 212 (-0.93%)
Mutual labels:  firebase
Flutter Music App
A Music app built using flutter
Stars: ✭ 212 (-0.93%)
Mutual labels:  firebase
Remember
The progressive offline Todo app
Stars: ✭ 208 (-2.8%)
Mutual labels:  firebase

ElmFire: Use the Firebase API in Elm

Virtually all features of the Firebase Web API are exposed as a library for Elm:

  • Setting, removing and modifying values
  • Transactions
  • Querying data, both one-time and per subscription
  • Complex queries with sorting, filtering and limiting
  • Authentication
  • User management
  • Offline capabilities

In addition to these base functions the package elmfire-extra provides a higher-level synchronization API, which allows you to treat your Firebase data like a local Elm-Dict.

Demo application for these APIs: Collaborative TodoMVC


This library currently targets Elm version 0.16.

A new version with an effect manager for Elm 0.17/0.18 is under development. Please stay tuned!


API Usage

The API design corresponds closely to the targeted Firebase JavaScript API. Please refer to the original documentation for further discussions of the concepts.

In the following we give a short overview of the API. Detailed documentation is embedded in the source code.

Constructing Firebase Locations

To refer to a Firebase path use a Location. It can be built with the following functions:

-- Location is an opaque type.
fromUrl  : String -> Location
sub      : String -> Location -> Location
parent   : Location -> Location
root     : Location -> Location
push     : Location -> Location
location : Reference -> Location

These are all pure functions. They don't touch a real Firebase until the resulting location is used in one of the tasks outlined below.

Example:

location : Location
location =
  fromUrl "https://elmfire.firebaseio-demo.com/test"
    |> parent
    |> sub "anotherTest"`
    |> push

References to Locations

Most actions on a Firebase location return a reference to that location. Likewise, query results contain a reference to the location of the reported value.

References can inform about the key or the complete URL of the referred location. And a reference may be converted back to a location, which can be used in a new task.

There is a special task to open a location without modifying or querying it, which results in a reference if the location is valid. It's generally not necessary to explicitly open a constructed location, but it may be used to check the validity of a location or to cache Firebase references.

-- Reference is an opaque type
key      : Reference -> String
toUrl    : Reference -> String
location : Reference -> Location
open     : Location -> Task Error Reference

Modifying Values

set             : Value -> Location -> Task Error Reference
setWithPriority : Value -> Priority -> Location -> Task Error Reference
setPriority     : Priority -> Location -> Task Error Reference
update          : Value -> Location -> Task Error Reference
remove          : Location -> Task Error Reference

These tasks complete when synchronization to the Firebase servers has completed. On success they result in a Reference to the modified location. They result in an error if the location is invalid or if you have no permission to modify the data.

Values are given as Json values, i.e. Json.Encode.Value.

Example:

port write : Task Error ()
port write =
  set (Json.Encode.string "new branch") (push location)
  `andThen`
  (\ref -> ... ref.key ... )

Transactions

Atomic modifications of the data at a location can be achieved by transactions.

A transaction takes an update function that maps the previous value to a new value. In case of a conflict with concurrent updates by other clients the update function is called repeatedly until no more conflict is encountered.

transaction : (Maybe Value -> Action) ->
              Location ->
              Bool ->
              Task Error (Bool, Snapshot)
type Action = Abort | Remove | Set Value

Example:

port trans : Task Error -> Task Error ()
port trans =
  transaction
    ( \maybeVal -> case maybeVal of
        Just value ->
          case Json.Decode.decodeValue Json.Decode.int value of
            Ok counter -> Set (Json.Encode.int (counter + 1))
            _          -> Abort
        Nothing ->
          Set (Json.Encode.int 1)
    ) location False
  `andThen`
  (\(committed, snapshot) -> ... )

Querying

once        : Query -> Location -> Task Error Snapshot
subscribe   : (Snapshot -> Task x a) ->
              (Cancellation -> Task y b) ->
              Query ->
              Location ->
              Task Error Subscription
unsubscribe : Subscription -> Task Error ()

Use once to listen to exactly one event of the given type.

The first parameter specifies the event to listen to: valueChanged, childAdded, childChanged, childRemoved or childMoved. Additionally, this parameter may also specify ordering, filtering and limiting of the query (see below). If you don't need these options a simple query specification is valueChanged noOrder.

The second parameter references the queried location.

Use subscribe to start a continuing query of the specified events. Subscription queries return a arbitrary number of data messages, which are reported via running a supplied task.

The first parameter of subscribe is a function used to construct that task from a data message.

The second parameter is a function used to construct a task that is run when the query gets canceled.

The third and fourth parameter of subscribe are the same as the first two of once.

On success the subscribe task returns a Subscription, an identifier that can be used to match the corresponding responses and to cancel the query.

type alias Snapshot =
  { subscription: Subscription
  , key: String
  , reference: Reference
  , existing: Bool
  , value: Value
  , prevKey: Maybe String
  , priority: Priority
  }
type Cancellation
  = Unsubscribed Subscription
  | QueryError Subscription Error

A Snapshot carries the resulting Value (as Json) among other information, e.g. the corresponding Subscription identifier.

In queries of type valueChanged the result may be that there is no value at the queried location. In this case existing will be False and value will be the Json value of null.

key corresponds to the last part of the path. It is the empty string for the root. Keys are relevant notably for child queries.

Example:

responses : Signal.Mailbox (Maybe Snapshot)
responses = Signal.mailbox Nothing

port query : Task Error Subscription
port query =
  subscribe
    (Signal.send responses.address << Just)
    (always (Task.succeed ()))
    (childAdded noOrder noLimit)
    (fromUrl "https:...firebaseio.com/...")

... = Signal.map
        (\response -> case response of
            Nothing -> ...
            Just snapshot -> ...
        )
        responses.signal

Ordering, Filtering and Limiting Queries

Query results can be ordered (by value, by a child's value, by key or by priority), and then filtered by giving a start and/or end value within that order, and limited to the first or last certain number of children.

Example queries to be used in once and subscribe:

childAdded noOrder
childAdded (orderByValue noRange noLimit)
childAdded (orderByChild "size" noRange noLimit)
childAdded (orderByKey noRange noLimit)
childAdded (orderByPriority noRange (limitToFirst 2))
childAdded (orderByValue (startAt (Json.Encode.string "foo")) noLimit)
childAdded (orderByValue (startAt (Json.Encode.string "foo")) (limitToLast 10))
childAdded (orderByChild "size" (equalTo (Json.Encode.int 42)) noLimit)
childAdded (orderByKey (endAt "k") noLimit)
childAdded (orderByPriority (startAt (NumberPriority 17, Just "k")) noLimit)

When doing ordered valuedChanged queries it may be useful to map the result to a list to conserve the ordering:

toSnapshotList : Snapshot -> List Snapshot
toValueList    : Snapshot -> List JE.Value
toKeyList      : Snapshot -> List String
toPairList     : Snapshot -> List (String, JE.Value)

Authentication

The sub-module ElmFire.Auth provides all authentication and user management functions that are offered by Firebase.

Some example tasks:

import ElmFire.Auth exposing (..)

-- create a new user-account with email and password
userOperation (createUser "[email protected]" "myPassword")

-- login with with email and password
authenticate loc [rememberSessionOnly] (withPassword "[email protected]" "myPassword")

-- login with with github account
authenticate loc [] (withOAuthPopup "github")

-- watch for logins and logouts
subscribeAuth
  (\maybeAuth -> case maybeAuth of
    Just auth -> ... auth.uid ...
    Nothing   -> ... -- not authenticated
  )
  loc

Offline Capabilities

  • Detecting connection state changes: subscribeConnected
  • Manually disconnect and reconnect: goOffline, goOnline
  • Managing presence: onDisconnectSet, onDisconnectSetWithPriority, onDisconnectUpdate, onDisconnectRemove, onDisconnectCancel
  • Handling latency: subscribeServerTimeOffset, serverTimeStamp

Examples

There is a basic example app in example/src/Example.elm. To build it:

cd example
make all open

Alternatively without using make:

cd example
elm make --output Example.html src/Example.elm

TodoMVC

A more extensive example is this implementation of TodoMVC as a collaborative real-time app.

Testing

There is a testing app, living in the directory test, that covers most of the code. It runs a given sequence of tasks on the Firebase API and logs these steps along with the several results.

This app uses a small ad-hoc testing framework for task-based code.

There is a Makefile to build the app. On most Unix-like systems a cd test; make all open should do the trick.

An older, still functional testing app lives in the directory demo.

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].