All Projects → blaugold → firebase-rxjs

blaugold / firebase-rxjs

Licence: other
Firebase with Observables, Type Checking of Schema, Zone.js aware and Angular ready.

Programming Languages

typescript
32286 projects
javascript
184084 projects - #8 most used programming language
shell
77523 projects

Projects that are alternatives of or similar to firebase-rxjs

Api
Promise and RxJS APIs around Polkadot and any Substrate-based chain RPC calls. It is dynamically generated based on what the Substrate runtime provides in terms of metadata. Full documentation & examples available
Stars: ✭ 232 (+1264.71%)
Mutual labels:  rxjs
rxremote
Subscribe to RxJs Observables on a remote server through a WebSocket
Stars: ✭ 27 (+58.82%)
Mutual labels:  rxjs
learnrxjs
Русскоязычная документация RxJS
Stars: ✭ 20 (+17.65%)
Mutual labels:  rxjs
Stuhome
📱 An iOS client for https://bbs.uestc.edu.cn/ written in react-native, redux and redux-observable.
Stars: ✭ 241 (+1317.65%)
Mutual labels:  rxjs
Rxdb
🔄 A client side, offline-first, reactive database for JavaScript Applications
Stars: ✭ 16,670 (+97958.82%)
Mutual labels:  rxjs
rdeco
响应式对象编程库,从时间和空间上解耦你的代码
Stars: ✭ 54 (+217.65%)
Mutual labels:  rxjs
Angular Ru Interview Questions
Вопросы на собеседовании по Angular
Stars: ✭ 224 (+1217.65%)
Mutual labels:  rxjs
thruway.js
RxJS WAMPv2 Client
Stars: ✭ 28 (+64.71%)
Mutual labels:  rxjs
ts-action-operators
TypeScript action operators for NgRx and redux-observable
Stars: ✭ 34 (+100%)
Mutual labels:  rxjs
react-nonav
Experimental React Native declarative navigation
Stars: ✭ 58 (+241.18%)
Mutual labels:  rxjs
Model
Angular Model - Simple state management with minimalist API, one way data flow, multiple model support and immutable data exposed as RxJS Observable.
Stars: ✭ 242 (+1323.53%)
Mutual labels:  rxjs
Rxjs Websockets
A very flexible and simple websocket library for rxjs
Stars: ✭ 248 (+1358.82%)
Mutual labels:  rxjs
gitlab-teams
🦊 Follow merge requests (&more) like a boss 🦊
Stars: ✭ 38 (+123.53%)
Mutual labels:  rxjs
Blog Angular
Angular 笔记
Stars: ✭ 238 (+1300%)
Mutual labels:  rxjs
deprecated-coalton-prototype
Coalton is (supposed to be) a dialect of ML embedded in Common Lisp.
Stars: ✭ 209 (+1129.41%)
Mutual labels:  static-typing
React Streams
Stars: ✭ 226 (+1229.41%)
Mutual labels:  rxjs
pirrigo
Full-featured Raspberry Pi based irrigation controller and web application for scheduling.
Stars: ✭ 18 (+5.88%)
Mutual labels:  zone
ngx-translate-module-loader
Highly configurable and flexible translations loader for @ngx-translate/core
Stars: ✭ 31 (+82.35%)
Mutual labels:  rxjs
observable-profiler
Tracks new & disposed Observable subscriptions
Stars: ✭ 41 (+141.18%)
Mutual labels:  rxjs
vuse-rx
Vue 3 + rxjs = ❤
Stars: ✭ 52 (+205.88%)
Mutual labels:  rxjs

FirebaseRxJS

Firebase with Observables, Type Checking of Schema, Zone.js aware and Angular ready.

  • Asynchronous results are returned as observables.
  • Strings in .child("pathSegment") can be validated through static type checking and a schema interface.
  • If zone.js is in scope firebase sdk runs in separate zone.
  • For use in angular apps FirebaseRxJSModule is provided.

[email protected] and [email protected] are required.

TypeScript Docs:

npm install --save firebase-rxjs
# For angular module
npm install --save firebase-rxjs-angular 

Configuration

Create a new FirebaseApp by passing in the config from Firebase Console.

import { FirebaseApp } from 'firebase-rxjs'

const app = new FirebaseApp({ options: {
    apiKey: "...",
    authDomain: "...",
    databaseURL: "...",
    storageBucket: "...",
    messagingSenderId: "..."
}});

// Get a reference to `FirebaseAuth`
const auth = app.auth()

auth.createUserWithEmailAndPassword("...", "...").subscribe(user => {
  ...
})

Usage

To get static type checking when accessing the database define a database schema interface. Its best to compose the schema out of smaller interfaces. This keeps your schema clear and allows you to easily access subsections with db.ref<SubSchema>('path/to/something').

// database-schema.ts
export interface UserProfile {
  firstName: string
  lastName: string
  twitter: string
  profileImg: string
}

export interface Comment {
  text: string
  createdAt: number
  author: string
  authorId: string
}

export interface Comments {
  [commentId: string]: Comment
}

export interface BlogPost {
  title: string
  summary: string
  body: string
  author: string
  authorId: string
  publishedAt: number
  updatedAt: number
  comments: Comments
}

export interface DBSchema {
  users: {
    [userId: string]: UserProfile
  }
  blogPosts: {
    [postId: string]: BlogPost
  }
}

Now when getting a reference of the database use the schema interface as the type parameter.

import { FirebaseApp } from 'firebase-rxjs'
import { DBSchema } from './database-schema.ts'

const app: FirebaseApp
const db = app.database<DBSchema>()

// Now the compiler will yell at you if you use the wrong path segments.
db.ref().child('userz')

// Or if you go deeper in the tree pass a sub schema as the type parameter.
const commentsRef = db.ref<Comments>('blogPosts/1/comments')

// Using a schema will also give you better IntelliSense when accessing the retrieved data.
commentsRef.onValue().list().subscribe(comments  => {
  comments[0].key
  comments[0].val.body
})

The result of onValue, onChildAdded, etc is a DataSnapshotObservable<T> which is typed according to the previous calls and the schema. It provides some helpful methods to make working with DataSnapshots easier, but the snapshots can be accessed directly too.

Most methods overall mirror the firebase sdk and behave the same.

Angular

Include the FirebaseRxJSModule in your root module. It is possible to provide multiple apps for injection but only one primary app. The primary FirebaseApp will make itself, FirebaseAuth and FirebaseDatabase injectable directly. Secondary apps have to be configured with an InjectionToken which will inject the FirebaseApp.

import { NgModule, InjectionToken } from '@angular/core'
import { FirebaseRxJSModule, FirebaseApp } from 'firebase-rxjs-angular'

const secondaryApp = new InjectionToken<FirebaseApp>()

@NgModule({
  ...
  imports: [
    FirebaseRxJSModule.primaryApp({options: ... }),
    FirebaseRxJSModule.secondaryApp(secondaryApp, {options: ... }),
  ],
  ...
})
export class AppModule {}

Zone.js

If Zone is globally available all calls to the firebase sdk will run in an isolated zone, forked from the root zone. Alternatively a zone can be passed to the FirebaseApp constructor. All other methods take the zone of their call site and schedule tasks with it.

Motivation for this feature is a problem which lets all protractor tests timeout unless synchronization is turned off. The cause lies in how protractor determines when changes stemming from the last input have propagated and the next instruction or expectation can be executed. It does this by observing whether or not MicroTasks and MacroTasks are scheduled to run. Once the queues of theses tasks are empty it's safe to assume the dom wont change. EventTasks like listeners on WebSocket.onmessage could run and change the dom but that is unpredictable and can not be factored in to the decision when to proceed with the test. Now what if micro and macro tasks schedule new tasks themselves? Protractor again will wait until all tasks have run. And this is what is problematic. When using the database the firebase sdk sends a heartbeat by setting up a timeout which first sends the heartbeat and then reschedules the next timeout. The result is a recursive chain of never ending MacroTasks keeping the task queue dirty. Independently of that the firebase sdk sets up a long running (around 30 seconds) timeout during initialization timing out any test by itself.

Real Time

Its worth noting that all write operations and one off reads are scheduled as MacroTasks, meaning protractor or angular's async test helper will wait until these tasks have run. This is not true for observables returned from .{on}{Value,ChildAdded,ChildRemove,ChildChanged,ChildMoved}(). The semantics of MacroTasks are that they are

guaranteed to execute at least once after some well understood delay.
For a real time databases like Firebase the correct tasks to use is the EventTask. This type of task is expected to run zero or multiple times with unpredictable timing. So when using the methods starting with `on`, tests relying on zone.js will not wait for them to complete, unless the framework is configured to wait for all EventTasks to be canceled. For each observable which emits real time database events the library schedules an EventTask on subscription and cancels it when the observable is unsubscribed. To make testing these kinds of observables simpler a test helper for the jasmine testing framework is included:
import { asyncEvents } from 'firebase-rxjs'

describe('Suite', () => {
  it('should wait for EventTasks to clear', asyncEvents(async () => {
    const db: FirebaseDatabase<any>
    // This observable will unsubscribe itself after emitting 3 events.
    db.ref().child('foo').onValue().take(3).subscribe()
    
    // Multiple observables or other asynchronous tasks will block the test until their 
    // resolution too.
    const res = await fetch('https://www.google.com')
  }))
})

End-to-end tests should poll content on the page under test, which is dependent on real time changes,
until a expected state is reached or timeout.

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].