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

WIP Support Firebase JS SDK 5.1 and Firestore with v3 #553

Merged
merged 76 commits into from
Feb 8, 2019
Merged

Conversation

jamesdaniels
Copy link
Contributor

@jamesdaniels jamesdaniels commented Jun 22, 2018

Description

This is a work in progress! A lot has changed since version 2 of emberfire was released. We wanted our third major release to work great with Ember v3+, Fastboot, Cloud Firestore, Cloud Functions, and modern security rules out of the box. We want to also deal completely with the weak points of version 2; namely relationships, querying, and performance.

Given all that has changed and all we want to accomplish, we thought best to rewrite.

I'll write up some more as this release closes but I wanted to throw my work in progress up here for people to check out. The work here is loosely based on my v3 proposal here #542 (I've refined a couple details while taking feedback and building things out).

Related issues #546 , #552 , #531, #529, #522, #512, #511, #465, #461, #400, etc.

To try out this branch run ember install emberfire-exp.

Code sample

Cloud Firestore adapter with offline-persistence enabled

// app/adapters/application.js
import FirestoreAdapter from 'emberfire/adapters/firestore';

export default FirestoreAdapter.extend({
    enablePersistence: true,
    persistenceSettings: { experimentalTabSynchronization: true }
})

Firestore backed model with embedded records, subcollections, and queries

// app/models/post.js
import DS from 'ember-data';
const { belongsTo, hasMany } = DS;

export default DS.Model.extend({
    user: belongsTo('user'),
    tags: hasMany('tags', { embedded: true }),
    comments: hasMany('comments', { subcollection: true, query: ref => ref.orderBy('publishedAt', 'asc') })
});

Route demonstrating Firestore querying capabilities & realtime route mixin

// app/routes/posts.js
import Route from '@ember/routing/route';
import { RealtimeRouteMixin } from 'emberfire/services/realtime-listener';

export default Route.extend(RealtimeRouteMixin, {
    model(params) {
        return this.store.query('post', ref => {
            const retVal = ref.orderBy('publishedAt', 'desc');
            if (params.tag) { return retValue.where(`tags.${params.tag}`, '==', true) }
            return retVal;
        })
    }
});

Firebase app service and ember-simple-auth integration

// app/controllers/application.js
import Controller from '@ember/controller';
import { inject as service } from '@ember/service';
import { get } from '@ember/object';
import firebase from 'firebase/app';

export default Controller.extend({
    session: service(),
    firebaseApp: service(),
    actions: {
        logout() {
            return get(this, 'session').invalidate();
        },
        async login() {
            const provider = new firebase.auth.GoogleAuthProvider();
            const auth = await get(this, 'firebaseApp').auth();
            return auth.signInWithPopup(provider);
        }
    }
});

Support for multiple Firebase applications / services

// config/environment.js

module.exports = function(environment) {
  let ENV = {
    firebase: [
      {
        apiKey: "...",
        authDomain: "YOUR_APP.firebaseapp.com",
        databaseURL: "https://YOUR_APPfirebaseio.com",
        projectId: "YOUR_APP",
        storageBucket: "YOUR_APP.appspot.com",
        messagingSenderId: "00000000"
      }, {
        apiKey: "...",
        authDomain: "YOUR_SECOND_APP.firebaseapp.com",
        databaseURL: "https://YOUR_SECOND_APP.firebaseio.com",
        projectId: "YOUR_SECOND_APP",
        storageBucket: "YOUR_SECOND_APP.appspot.com",
        messagingSenderId: "0000000",
        name: "second-app"
      }
    ],
    ...

After initialization there will now be a service:firebase-app and service:firebase-second-app ready for injection.

TODO

  • Get the first pass of the realtime service in
  • Get the test suite together and passing
    • Flush out the test suite
    • Give the relationship system a good once over
  • Setup Travis with the NPM keys and cut beta.1
  • Consider Fastboot Authentication (admin cookies, express middleware?)
  • Put together migration guide
  • Update the documentation
  • Publish API reference
    • Add class descriptions, parameter comments, code examples, and more tsdocs
    • Add links to the API reference from the docs
    • Clean up external types
    • Remove external Defined in references to my node_modules
  • Reassess ember-auto-import, browserify, and browserify-shim as we near final
  • Reassess shoebox as we near final
  • Initializer should bring in the serializer
  • Should not require ember-simple-auth, etc.

more to come...

@brendanoh brendanoh mentioned this pull request Dec 12, 2018
@chadRoberge

This comment has been minimized.

@jamesdaniels
Copy link
Contributor Author

jamesdaniels commented Feb 7, 2019

I've published on NPM under emberfire-exp for the time being.

ember install emberfire-exp

Copy link

@zoltan-nz zoltan-nz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After a quick test:

  1. I noticed, that ember-simple-auth cannot be optional, it has be installed to the project with ember install ember-simple-auth. (v1.8.1 is installed)
  2. The default adapter configuration changed and has to be updated to FirestoreAdapter as you already mentioned in the new guide
import FirestoreAdapter from 'emberfire/adapters/firestore';
export default FirestoreAdapter.extend({
});
  1. After my demo app compiled and opened, when the router wanted to access to the store/adapter first time, the following error appeared:
Class constructor FirestoreAdapter cannot be invoked without 'new' TypeError: Class constructor FirestoreAdapter cannot be invoked without 'new'

My app uses Ember / EmberData v3.4 LTS.

package.json Outdated Show resolved Hide resolved
@jamesdaniels
Copy link
Contributor Author

Yeah I'll make simple auth an optional dependency. Also I noticed that the serializer isn't coming in, so you'll want to create an application serializer that extends the one in Emberfire. I'll fix that shortly.

Not sure about your 'new' issue. Might be the ember version.

@samselikoff
Copy link

@zoltan-nz I ran into the same error you did:

Class constructor FirestoreAdapter cannot be invoked without 'new' TypeError: Class constructor FirestoreAdapter cannot be invoked without 'new'

Did you ever figure it out?

@zoltan-nz
Copy link

@samselikoff do you use Ember v3.4? I think, the latest beta version of EmberFire works fine with Ember v3.5+

So the solution was to upgrade Ember.

I would say, we should use EmberFire v2 until Ember v3.4 and use EmbeFire v3(beta) with Ember v3.5+

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.