mikkopaderes / ember-cloud-firestore-adapter Goto Github PK
View Code? Open in Web Editor NEWUnofficial Ember Data Adapter and Serializer for Cloud Firestore
License: MIT License
Unofficial Ember Data Adapter and Serializer for Cloud Firestore
License: MIT License
Hi @mikkopaderes, I'm having a few issues loading records with a hasMany relationship. I have some customers
that can have many bookings
. As per the docs, a reference to each root-level booking is stored in each customer's sub-collection.
When I store.findAll('booking', {})
I get all bookings and if I subsequently run customer.bookings.toArray()
I can see the relevant records for that one customer. However, if I skip the first step (i.e. I don't load all bookings first) the second query returns an empty array.
I'm I missing something, or assuming a behaviour that's not in your design?
Could you flesh out the architecture of using a service worker connected to a functions app server? I must be missing a puzzle piece since my service worker doesn't try to connect to my running functions port to get the correct custom tokenID. Instead, since it doesn't use the functions app server, the tokenID it has is "incorrect", which means it's not authenticated in fastboot. I'm hoping for a little more guidance in setting this up.
Lets say I have post model and posts collection and elsewhere in my db I have a sub-collection of posts that are docs with a referenceTo field to the actual posts collection.
If I perform a query on the sub-collection and one of the reference fields references a post that doesn't exist the query rejects (findRecord rejects on falsy snapshop.exists
property) eg.
this.store.query('post', {
buildReference(db) {
return db.collection('some').doc('docWithPostSubCollectionOfReferenceTos').collection('posts');
}
}
rejects if one of the references is broken.
But given that Firestore operates in the mode that a given DocumentReference will return a DocumentSnapshot with an exists property = false if there is no snapshot at the reference, would it be more more appropriate for the adapter to return a record that satisfies the DS.Model isEmpty state?
(In my particular scenario, I have instances where the referenceTo field can legitimately exist without the referenced record - long running cascading delete functions that run on an onDelete trigger. If the user goes elsewhere in the app I would prefer the queries to succeed and handle the isEmpty records in template logic.)
Maybe an adapterOptions
to determine how missing references are handled?
const newPost = this.store.createRecord('post', { title: 'Post A' });
the error is "Cannot read property 'toString' of undefined TypeError: Cannot read property 'toString' of undefined"
in the function
generateIdForRecord(_store, type) {
const db = this.firebase.firestore();
const collectionName = (0, _buildCollectionName.default)(type.modelName);
return db.collection(collectionName).doc().id;
}
var type is just string (Model name) so type.modeName is undefined
Hi @mikkopaderes, thanks for a great adapter!
I have collections clients -> athletes and clients -> teams. everything works great. I can access athletes and teams with calls like client.get('athletes)
and client.get('teams')
.
when i add a many-to-many relationship between athletes and teams everything mostly works as expected but i can no longer use accessors to retrieve child items. eg. if in a model hook i have loaded a team then any attempt to load a team's athletes via team.get('athletes')
will return an empty recordset and i can only retrieve a team' s athletes via a store.query
.
If I inspect the buildReference for a team's athletes, the path appears as team\:team_id\athletes
. I'm guessing this would need to be clients\:client_id\teams\:team_id\athletes
but I don't know how this would be doable in a model definition?
Thanks for the grate work!
I was wondering if there is a reason that many to many references are stored in a subcollection and not an array? This is costs time and money as a lot more documents need to be read.
Thanks for the feedback!
Hi @mikkopaderes. Hope you are keeping safe.
This is not so much an issue with this addon perse but a request for assistance. You have exposed the firebase API for sign in with email and password but I am struggling to enable "signInWithPhoneNumber". Would you be able to give me some pointers on this? I tried to follow the firebase authentication documentation to no avail.
I have created a repository with a working implementation of your "auth.signInWithEmailAndPassword" here: git clone https://[email protected]/alexmasita/kenya.united.git
.
It is a public repo. I have implemented the sign-in method in the "sign-in" component which works. You can also see the commented sections where I tried to implement the "signInWithPhoneNumber". The error I kept getting was on the following code:
//Predicated the firebase handle with this. as you have exposed it as service in your library.
window.recaptchaVerifier = new this.firebase.auth.RecaptchaVerifier('sign-in-button', {
'size': 'invisible',
'callback': function(response) {
// reCAPTCHA solved, allow signInWithPhoneNumber.
onSignInSubmit();
}
});
Specifically, I was getting new this.firebase.auth is not a constructor
. I tried to change it to new this.firebase.auth().
to include the opening and closing braces but it was throwing a different error that says something like cannot call bind of undefined
which seems to be thrown inside the vendor/fastboot-shims/firebase/firebase-app.js
Let me know if you can help.
User Story:
As a user, I want to be able to conditionally apply multiple filters when querying Firebase.
Given 3
query parameters that are mutated by the User from the UI;
In model hook, I want to build the query based on params
that the user interacted to.
Code example
model(params) {
return this.store.query('modelName', {
filter(reference) {
return reference
.orderBy('property-1')
.where('property-1', '>', params['queryParam-1']) // executed **only** when the user changes queryParam-1 query
.where('property-1', '<', params['queryParam-2']) // executed **only** when the user changes queryParam-2 query
.where('property-2', '==', params['queryParam-3']) // executed **only** when the user changes queryParam-3 query
}
})
}
Ideas here cool. Like to implement. Much awesome. Snippets below.
const userId = 'user_a';
this.store.query('user', {
// Not overriding this hook will point to db.collection('users')
buildReference(db) {
return db.collection('users').doc(userId).collection('friends');
},
filter(reference) {
return reference.where('age', '>=', 18).limit(10);
}
});
this.store.findRecord('user', 'user_id', {
adapterOptions: {
buildReference(db) {
return db.collection('admins');
}
}
});
Old API will be removed. π’
Hey @rmmmp I'm so pumped for the future of Firestore, and I'm so grateful that you took the time to do this! Honestly, I want to start using this right away in a new project.
However, how should I handle authentication?
Hi @mikkopaderes and thanks for this project, it's been a blessing!
Our app has been running nicely with the current version of the add-on for months. For whatever reason, we've ended up with [email protected] installed as a dev dependency. That's not been a problem until today, when I tried to test the app against the latest version of Ember, via ember-try. When I did, it refused to play ball because your add-on has [email protected] as a peer dependency. I tried rolling back to that version but that broke the app - auth doesn't appear to be working properly and that's preventing the adaptor resolving requests π’
Currently, the only way I can get the app working is with @9.0.1 as a dev dependency.
Before I throw myself into another day of debugging, is there a rationale for having the legacy dependency as a peer? I note that @9.0.1 is in your own dev dependencies, so it seems odd at first glance.
Any context / thoughts would be greatly appreciated ππ»
Hi,
thanks for the handy adapter.
I've stumbled upon a problem while trying to model a document with a subcollection. I tried using a hasMany relationship, but it seems like it's always searching for a root collection?
export default DS.Model.extend({
fragments: hasMany('fragment') // this should be a subcolletion in firestore
});
Is there a way to access a subcollection in a oneToMany relationship ?
Are belongsTo associations to documents in subcollections supported or planned? For example:
belongsTo('user') --> docRef: /groups/mygroup/users/me
Currently works as I'd expect if user with id 'me' is already in the store. If the user is not in the store however it is retrieved from '/users/me' despite the docRef stored.
We have an existing ember app using the adapter and we added Firebaseβs βnewishβ performance monitoring service. The drop-in http profiling is very limited and groups all of our Firestore queries into one big bucket.
What would you recommend as the best approach to capturing more fine grained custom traces of Firestore interactions made through your adapter? Any tips or generally direction is greatly appreciated.
Currently this doesnt return any values in my app:
{ adapterOptions: { isRealtime: false } }
However this gives me records but also socketio errors:
{ adapterOptions: { isRealtime: true } }
Anyone else had this issue?
Docs doesn't mention how you setup the serializer.
It was pretty guessable though.
After generating an application serializer with ember generate serializer application
One needs to change the file content to:
import CloudFirestoreSerializer from 'ember-cloud-firestore-adapter/serializers/cloud-firestore';
export default class ApplicationSerializer extends CloudFirestoreSerializer {
}
@mikkopaderes. This Addon is great so far and I would not want to raise this as an issue but an enhancement. It would be great if the Find Record firebase calls could work in fastboot as well so we:
I would assume the adapter would need to be re-architected in such a way as to be able to use node firebase libraries to retrieve the data.
As stated, this is not an issue, so feel free to close it if you think it is not something that could be on your road map soon. I would be willing to look into this as well with a view to submit a pull request. Thank you.
Hi @mikkopaderes. Have been refactoring my app to clean out the fastboot checks. Have hit a snug that appears related to the real time tracker that you enable in the route model as seen here:
model(_params) {
return this.store.findRecord('rider', get(this, 'session.data.authenticated.user.uid'), {
adapterOptions: {
isRealtime: true //When enabled breaks the fastboot runtime but loads correctly on client
}
});
}
The error I receive is the following:
DEPRECATION: Attempted to call store.peekRecord(), but the store instance has already been destroyed. [deprecation id: ember-data:method-calls-on-destroyed-store]
at logDeprecationStackTrace (/Users/alexmasita/External/Personal/projects/Ember-Apps/mobile-services-app/dist/assets/@ember/debug/lib/deprecate.js:103:1)
at HANDLERS.(anonymous function) (/Users/alexmasita/External/Personal/projects/Ember-Apps/mobile-services-app/dist/assets/@ember/debug/lib/handlers.js:23:1)
at raiseOnDeprecation (/Users/alexmasita/External/Personal/projects/Ember-Apps/mobile-services-app/dist/assets/@ember/debug/lib/deprecate.js:130:1)
at HANDLERS.(anonymous function) (/Users/alexmasita/External/Personal/projects/Ember-Apps/mobile-services-app/dist/assets/@ember/debug/lib/handlers.js:23:1)
at invoke (/Users/alexmasita/External/Personal/projects/Ember-Apps/mobile-services-app/dist/assets/@ember/debug/lib/handlers.js:35:1)
at Object.deprecate (/Users/alexmasita/External/Personal/projects/Ember-Apps/mobile-services-app/dist/assets/@ember/debug/lib/deprecate.js:168:1)
at assertDestroyedStore (/Users/alexmasita/External/Personal/projects/Ember-Apps/mobile-services-app/dist/assets/addon-tree-output/ember-data/-private.js:12941:1)
at Class.peekRecord (/Users/alexmasita/External/Personal/projects/Ember-Apps/mobile-services-app/dist/assets/addon-tree-output/ember-data/-private.js:11016:1)
at Object.docRef.onSnapshot.docSnapshot [as next] (/Users/alexmasita/External/Personal/projects/Ember-Apps/mobile-services-app/dist/assets/addon-tree-output/ember-cloud-firestore-adapter/utils/realtime-tracker.js:39:1)
at next (/Users/alexmasita/External/Personal/projects/Ember-Apps/mobile-services-app/node_modules/@firebase/firestore/src/api/database.ts:1135:20)
at Timeout._onTimeout (/Users/alexmasita/External/Personal/projects/Ember-Apps/mobile-services-app/node_modules/@firebase/firestore/src/util/async_observer.ts:51:11)
at ontimeout (timers.js:436:11)
at tryOnTimeout (timers.js:300:5)
at listOnTimeout (timers.js:263:5)
at Timer.processTimers (timers.js:223:10)
DEPRECATION: Attempted to call store.hasRecordForId(), but the store instance has already been destroyed. [deprecation id: ember-data:method-calls-on-destroyed-store]
at logDeprecationStackTrace (/Users/alexmasita/External/Personal/projects/Ember-Apps/mobile-services-app/dist/assets/@ember/debug/lib/deprecate.js:103:1)
at HANDLERS.(anonymous function) (/Users/alexmasita/External/Personal/projects/Ember-Apps/mobile-services-app/dist/assets/@ember/debug/lib/handlers.js:23:1)
at raiseOnDeprecation (/Users/alexmasita/External/Personal/projects/Ember-Apps/mobile-services-app/dist/assets/@ember/debug/lib/deprecate.js:130:1)
at HANDLERS.(anonymous function) (/Users/alexmasita/External/Personal/projects/Ember-Apps/mobile-services-app/dist/assets/@ember/debug/lib/handlers.js:23:1)
at invoke (/Users/alexmasita/External/Personal/projects/Ember-Apps/mobile-services-app/dist/assets/@ember/debug/lib/handlers.js:35:1)
at Object.deprecate (/Users/alexmasita/External/Personal/projects/Ember-Apps/mobile-services-app/dist/assets/@ember/debug/lib/deprecate.js:168:1)
at assertDestroyedStore (/Users/alexmasita/External/Personal/projects/Ember-Apps/mobile-services-app/dist/assets/addon-tree-output/ember-data/-private.js:12941:1)
at Class.hasRecordForId (/Users/alexmasita/External/Personal/projects/Ember-Apps/mobile-services-app/dist/assets/addon-tree-output/ember-data/-private.js:11072:1)
at Class.peekRecord (/Users/alexmasita/External/Personal/projects/Ember-Apps/mobile-services-app/dist/assets/addon-tree-output/ember-data/-private.js:11024:1)
at Object.docRef.onSnapshot.docSnapshot [as next] (/Users/alexmasita/External/Personal/projects/Ember-Apps/mobile-services-app/dist/assets/addon-tree-output/ember-cloud-firestore-adapter/utils/realtime-tracker.js:39:1)
at next (/Users/alexmasita/External/Personal/projects/Ember-Apps/mobile-services-app/node_modules/@firebase/firestore/src/api/database.ts:1135:20)
at Timeout._onTimeout (/Users/alexmasita/External/Personal/projects/Ember-Apps/mobile-services-app/node_modules/@firebase/firestore/src/util/async_observer.ts:51:11)
at ontimeout (timers.js:436:11)
at tryOnTimeout (timers.js:300:5)
at listOnTimeout (timers.js:263:5)
at Timer.processTimers (timers.js:223:10)
I discovered the error disappears when I remove the following adapter options setting:
adapterOptions: {
isRealtime: true
}
I however need the real time aspects on the client. Might you know a work-around for this?
Hi,
First of all, thanks for the great tool!!
I am trying to add a child to a parent doc with a many-to-none relationship between them. But both object exists before I create the relationship. (I use version 0.5.0 of the adapter)
Parent model:
children: hasMany('child', {
inverse: null,
buildReference(db, record) {
return db.collection('parents').doc(record.get('id')).collection('children');
}
}),
The child model doesn't have a reference to the parent, because I don't need that.
When a user adds a child to a parent, I am doing:
parent.get('children').pushObject(child);
My question is, how do I persist this in the database?
If I do parent.save()
it doesn't create a subcollection reference to the child. Also parent.get('hasDirtyAttributes')
returns false
.
Maybe I just don't find this in the docs. In that case sorry for the inconvenience, but could you direct me to a solution?
Thanks in advance!
Hey @rmmmp, I get an error with a fresh install of your plugin:
Build Canceled: Broccoli Builder ran into an error with `Concat` plugin. Γ°ΕΈβΒ₯ ENOENT: no such file or directory, open '/Users/Benjamin/Sites/my-project/tmp/source_map_concat-input_base_path-XIEBNak7.tmp/node_modules/firebase/firebase.js'
I tried a basic rm -rf node_modules
+ yarn install
but it didn't do it. Do you have any ideas why? To me it looks like it's not linking well with ember-firebase-service
.
I didn't have the problem in 0.2.0
.
Spin-off from the discussions in #150
User Story:
As a user, I want to support buildReference
on a one-to-many relationship, so that I can choose to save my records under any collections/sub-collections
Acceptance Criteria:
buildReference
on hasMany
one-to-many relationship typebuildReference
on belongsTo
relationships
Reference
data type property.buildReference
and simply fetch whatever the Reference
data type resolves toI have models that are in a subdirectory of my models folder e.g. models/other/contract
. I think they are called "namespaced models" in the docs. I am not referring to subcollections.
When I save these namespaced models, I get the following error:
Invalid collection reference. Collection references must have an odd number of segments, but other/contracts has 2
So it seems the adapter is trying to write to a collection with a slash in the collection identifier. I can get around the error by rewriting the Firestore collection name as other.contracts
, but is there a recommended way of doing this?
Please publish a dummy application or provide working examples of configuring data models for various relationships, including examples of CRUD methods.
For example, I'm having a hard time configuring two models with many-to-many relationships, where references are stored in their respective sub-collections.
TODO:
ember-firebase-service
to v8.0.0
#125mock-cloud-firestore
mock-cloud-firestore
from projectfirestoreSettings
to config/environment.js
instance-initializer
Given a model Comment
that belongsTo User
(User hasMany Comments).
Since one-to-many relationships only keep the reference in the belongsTo side.
What should be the preferred way to query all comments from a specific User?
Great work on this.
Would like to migrate to this from emberfire but has the authentication story been fleshed out? With emberfire we can add authentication to the app using a torii provider built into EmberFire and the library emberfire-utils
has a handy addon firebase-ui-auth
which makes authentication integration a breeze.
In firebase client libraries, it is possible to use for instance a user id as the id on multiple objects containing that user's information.
In this particular case, I find myself wanting to extend firebase auth object with additional attributes and it would be nice to pick the user id from the session object and create a profile document whose id is the same as the current session's user id.
Is there a way to do it currently when creating a new model via get(this, 'store').createRecord('profile',{})
where you can pass the current session user id as the profile model id?
Hi, thanks for your work!
I'm trying to do the authentication with Google, taking the same example they have:
var provider = new firebase.auth.GoogleAuthProvider();
firebase.auth().signInWithPopup(provider).then(function(result) {
// This gives you a Google Access Token.
var token = result.credential.accessToken;
// The signed-in user info.
var user = result.user;
});
I translated the code to use your authentication and the firebase service, and the issue I have is creating the provider:
var provider = new this.firebase.auth.GoogleAuthProvider();
because this.firebase.auth.GoogleAuthProvider
is undefined but this.firebase.auth()
does exist. If I use firebase from window it works:
var provider = new window.firebase.auth.GoogleAuthProvider();
The firebase service has the this.firebase.auth()
but no this.firebase.auth.GoogleAuthProvider
Any ideas why this is happening? thanks!
As seen on the official docs, Cloud firestore enables you to use the cache when you loose the internet connection so that the app does not break. Is there an easy way to configure this here?
You can check out the article here: firestore enable persistence link
It would be great to be able to easily manually disable and enable network access programmatically as seen on that page as well.
Thank you.
the adapter's findRecord etc call an underlying fetchRecord function which rejects with a js Error object when a record isn't found:
reject(new Error(
Record ${id} for model type ${type.modelName} doesn't exist));
It would be nice if this error object also had a name property not-found
making it easier to identify the specific error. 'not-found' would match the naming conventions of the FirestoreError class.
There was a check for this before which I probably removed by mistake while migrating files to TypeScript. Maybe due to unfortunate circumstances I didn't have regression tests to capture this. Will need to add it back and also add tests so this doesn't happen again.
When fetching a model called blog-post in emberfire I used to call
this.store.findAll('blog-post');
But with this adapter i have to use:
this.store.findAll('blogPost');
Is this intentional?
Brendan
Firebase auth uses JWT tokens for authentication, not cookies. JWT tokens are short live so if we pass that in to the server through cookies and verify it, there's a high chance that it's already expired.
Service workers might work although I haven't tried this solution yet.
Here's the flow of I think FastBoot auth could work:
fetch
and modify to add the result of getIdToken()
verifyIdToken()
.createCustomToken()
.restore()
hook. We'll be using signInWithCustomToken()
to finally sign in the user.This addon can support points 1 and 5 although I'm still contemplating if we should have 1 built-in. Points 2, 3, and 4 would have to be done in the FastBoot server which is out of our control.
One can build references and hence save into sub-collections like:
this.get('store').findRecord('user', 'user_a').then((user) => {
this.get('store').createRecord('post', {
body: 'New Post Body',
title: 'New Post Title',
author: user
}).save({
adapterOptions: {
buildReference(db) {
return db.collection('users').doc('user_b').collection('feeds');
}
}
});
});
But if I set such a sub-collection doc as a relation - like in the above example instead of post -> user
you would set user -> post
- it will always be serialized as a root-collection (see https://github.com/rmmmp/ember-cloud-firestore-adapter/blob/master/addon/serializers/cloud-firestore.js#L91).
Is this intentional or a bug?
Hello! I'm attempting to upgrade one of our apps to Ember 3.26. The app itself seems to work okay but I am encountering some new errors that seem to be related to this add-on. For example, this test:
import { module, test } from 'qunit';
import { setupRenderingTest } from 'ember-qunit';
import { render } from '@ember/test-helpers';
import { hbs } from 'ember-cli-htmlbars';
module('Integration | Component | video-list-item', function (hooks) {
setupRenderingTest(hooks);
hooks.beforeEach(async function () {
await this.owner
.lookup('service:session')
.authenticate('authenticator:oneday-firebase', (auth) => {
return auth.signInWithEmailAndPassword(email, password);
});
});
hooks.afterEach(async function () {
await this.owner.lookup('service:session').invalidate();
});
test('it renders', async function (assert) {
let store = this.owner.lookup('service:store');
const video = await store.findRecord('video', '7Qdgy5xYVOErF86idWaz');
this.set('video', video);
await render(hbs`<VideoListItem @video={{this.video}} @index=1 />`);
assert.dom('[data-test-video-list-item]').exists();
});
});
Results in the following error, which I was not seeing prior to the upgrade:
Uncaught (in promise) Error: endAsync called with no preceding beginAsync call.
The above error is accompanied by the following warning:
WARNING: Async Request leaks detected. Add a breakpoint here and set `store.generateStackTracesForTrackedRequests = true;`to inspect traces for leak origins:
- DS: Handle Adapter#findHasMany of 'video' : 'stage'
- DS: Handle Adapter#findHasMany of 'video' : 'subject'
The component itself is pretty simple. The template renders some details of the Video model it is handed. This includes listing out the titles of any related Stages and Subjects. The model definition looks like this:
import Model, { attr, hasMany } from '@ember-data/model';
export default class VideoModel extends Model {
@attr('string') title;
@hasMany('stage', {
isRealtime: true,
})
stages;
@hasMany('subject', {
isRealtime: true,
})
subjects;
get heading1() {
return this.title;
}
}
What appears to be happening is that Ember Data is loading the relationships asynchronously and Ember's testing tools are not happy about it. I understand why, but I don't know what alternative strategy I could use.
I had a good chat with a colleague, his reaction was "why don't you just stub out the store and mock some data?" For the test above, that would be fine, but I have an acceptance test that gets the same errors and warnings:
import { module, test } from 'qunit';
import { visit, currentURL } from '@ember/test-helpers';
import { setupApplicationTest } from 'ember-qunit';
module('Acceptance | user can view list of videos', function (hooks) {
setupApplicationTest(hooks);
hooks.beforeEach(async function () {
await this.owner
.lookup('service:session')
.authenticate('authenticator:oneday-firebase', (auth) => {
return auth.signInWithEmailAndPassword(email, password);
});
});
hooks.afterEach(async function () {
await this.owner.lookup('service:session').invalidate();
});
test('visiting /videos', async function (assert) {
await visit('/videos');
assert.equal(currentURL(), '/videos', 'the videos route can be accessed');
assert.dom('[data-test-simple-filter]').exists('the filter tools exist');
assert.dom('[data-test-video-list]').exists('the list of videos exist');
});
});
The Route being accessed by this acceptance test makes the following requests to the Store:
import Route from '@ember/routing/route';
import { inject as service } from '@ember/service';
export default class VideoRoute extends Route {
@service store;
async model() {
const videos = await this.store.findAll('video', { reload: true });
const model = videos.filter((v) => !!v.published);
await this.store.findAll('stage', { reload: true });
await this.store.findAll('subject', { reload: true });
return model;
}
}
Implicitly, this is testing that a) a user can authenticate via the Auth emulator, b) a request made by that user passes the Firebase security rules, c) the Firestore emulator returns what we need for rendering in the app, d) the relevant bits get rendered in the DOM. If I were to stub all that out, I'm not sure how valid that test would be. I certainly couldn't use it in a CI context.
This leaves me wondering how others are testing their Ember apps using this add-on, using the Firebase Emulator suite? Are there other strategies that I should be considering? Are there obvious problems with the tests I've included above that could be addressed? Do I need to use Ember testing for basic render testing and something else for end-to-end tests and CI integration? I'm I naive to think I can get end-to-end tests working in this way?
Any and all feedback is extremely welcome. Thanks!
@rmmmp , I have hit the following issue:
TypeError: _this4.get(...).firestore is not a function
at /Users/alexmasita/External/Personal/projects/Ember-Apps/mobile-services/tmp/broccoli_persistent_filterautoprefixer_filter-output_path-xEKeiDYd.tmp/assets/addon-tree-output/ember-cloud-firestore-adapter/adapters/cloud-firestore.js:161:1
at initializePromise (/Users/alexmasita/External/Personal/projects/Ember-Apps/mobile-services/tmp/broccoli_persistent_filterautoprefixer_filter-output_path-xEKeiDYd.tmp/assets/rsvp.js:418:1)
........There is more code below this truncated for brevity..........
This issue disappears when I put the following code in my route:
model() {
if (get(this, 'fastboot.isFastBoot')) return;
return get(this, 'store').findAll('vehicle');
}
It means their needs to be a fastboot check somewhere in the adapter that negates the need for this check. What do you think?
The new API will replace the current way to specify a path and batch writes for a more Cloud Firestore way.
Here's a sample
const user = this.store.createRecord('user', {
age: 15,
});
user.save({
adapterOptions: {
buildReference(db) {
return db.collection('admins');
},
include(batch, db) {
const userMetaRef = db.collection('notifications').doc(user.get('id'));
batch.set(userMetaRef, {
numOfFriends: 0,
numOfNotifications: 0
});
}
}
});
Hi @mikkopaderes. Thanks for your continued awesome work on this. I am getting the above warning in my console when I implement the ESA authentication solution as seen in your guides here. Everything seems to work perfectly but that warning might signify a problem that might stump me later. Is this a known issue from your end?
You can see from the following screenshot: Console View that even with the warning, the session's isAuthenticated property is true and I am able to get session authenticated data.
I am also getting odd behaviour where on my (fastboot) app refresh, the session appears not to stay authenticated as it goes to the authentication page. I have enabled fastboot support according to the Ember Simple Authentication documentation by using only the cookie session store but to no avail. When I disable fastboot, the session is restored correctly. Perhaps you can advise me on this as well if you can?
Let me know.
Just wanted to point out that currently a batch defined via the include option which holds more changes than 500 write operations (which is the limit defined by Google Firestore) will cause the whole write operation to fail.
One option would be to split all batched mutations up into multiple batches of 500 and finally invoke their commit.
By default, the adapter listens for real-time changes. I've done this by default just to keep the similarities with Firebase Realtime DB. I've since realized then that listening for real-time changes should be opt-in.
Should we make real-time updates opt-in, this will introduce a breaking change.
First of all, thank you very much for this addon. It's exactly what I was looking for after revisiting Emberfire and finding it in WIP and basically abandoned state. I love the lightweight, flexible, no-nonsense approach you took.
I'm looking for a way to "namespace" the default read/write operations at the adapter/serializer level. My use case would be similar to the emberfire namespace
attribute on the firestore adapter. For example if I had a model "item" and wanted the "items" collection to be written to/read from at environments/<build env>/users/<uid>/items
instead of just root items
it would be very nice to just have to specify a namespace in one place like the adapter e.g. something like
get namespace() {
return `/environments/${config.environment}/users/${this.currentUser.userId}`;
}
Is this possible currently? And if not would you be open to supporting something like this? I'd be happy to contribute a PR if so.
We are getting the following error after installing this Addon: EMFILE: too many open files, watch
.
It's replicable across multiple machines.
Is this something you've encountered before?
I've found that the User object passed by onAuthStateChanged()
in the restore()
method of FirebaseAuthenticator
is sometimes null when multiple instances of the Ember app are running.
Steps to recreate:
await this.session.authenticate('authenticator:firebase', (auth) => {
return auth.signInWithEmailAndPassword(email, password);
});
This screenshot is from the second tab after logging into the first:
It seems to be some sort of timing issue. Logging this.session.data.authenticated.user
in the immediate post-authentication route produces null
about half of the time. I can then refresh the page, and then the restore()
method is able to find the session data (and the user object) again.
Any ideas?
Much idea similar here. Like to implement. Need to test feasibility first. Snippet below.
import { hasMany } from 'ember-data/relationships';
import Model from 'ember-data/model';
import attr from 'ember-data/attr';
export default Model.extend({
age: attr('number'),
username: attr('string'),
friends: hasMany('user', {
filter(reference, record) {
return reference.where('age', '>=', record.get('age')).limit(10);
}
}),
});
Here's how to change the relationship option dynamically for use-cases such as changing filter
hook to increase the limit
for infinite scrolling/pagination.
Disclaimer: I'm not sure if changing the relationship option has any drawbacks in Ember Data. I assume that there's none as long as you don't change built-in options such as async
, inverse
, etc..
const user = await this.store.findRecord('user', 'user_a');
const friends = await user.get('friends');
const newLimit = 20;
friends.relationship.relationshipMeta.options.filter = (reference, record) => {
return reference.where('age', '>=', record.get('age')).limit(newLimit);
};
friends.reload();
Shows the following error
Function Firestore.settings() requires its first argument to be of type object, but it was: a custom Object object
Not sure why it's getting picked up as a custom Object object
. Even though I've just hard coded it to pass-in {}
, new Object()
, Object.assign({})
, it doesn't work.
I'm inclined to think that this is a Firebase issue but I'm unable to replicate it in a Node environment. If all else fail, my workaround would be to let the deprecation in #43 reappear and wait until we no longer need to execute Firebase.settings()
due to timestampsInSnapshots
defaulting to true
in the future.
EDIT:
Workaround would be to set firestoreSettings: null
in your adapter. As a result, the Firestore deprecation will show up.
Currently, the instance-initializer is hard to understand and test. This should be rewritten in a new class to make it more maintainable and testable.
Build failed.
Build Error (Concat)
ENOENT: no such file or directory, open '/Users/xxxxxxxx/development/cfireview/clean-pods/tmp/source_map_concat-input_base_path-i7wWgn1z.tmp/node_modules/firebase/firebase-firestore.js'`
ENV Summary:
TIME: Sat Jan 27 2018 20:54:24 GMT-0500 (EST)
TITLE: ember
ARGV:
- /Users/xxxxxxxx/.nvm/versions/node/v8.9.4/bin/node
- /usr/local/bin/ember
- build
EXEC_PATH: /Users/xxxxxxxx/.nvm/versions/node/v8.9.4/bin/node
TMPDIR: /var/folders/y_/z1hh7_lj6vd814ycqvqp6g2c0000gn/T
SHELL: /bin/zsh
PATH:
- /Users/xxxxxxxx/.nvm/versions/node/v8.9.4/bin
- /Users/xxxxxxxx/anaconda3/bin
- /Users/xxxxxxxx/.dnx/bin
- /usr/local/heroku/bin
- /Users/xxxxxxxx/.rbenv/shims
- /Users/xxxxxxxx/bin
- /usr/local/bin
- /usr/bin
- /bin
- /usr/sbin
- /sbin
PLATFORM: darwin x64
FREEMEM: 90284032
TOTALMEM: 17179869184
UPTIME: 119661
LOADAVG: 2.96044921875,2.6064453125,2.76611328125
CPUS:
- Intel(R) Core(TM) i7-4980HQ CPU @ 2.80GHz - 2800
- Intel(R) Core(TM) i7-4980HQ CPU @ 2.80GHz - 2800
- Intel(R) Core(TM) i7-4980HQ CPU @ 2.80GHz - 2800
- Intel(R) Core(TM) i7-4980HQ CPU @ 2.80GHz - 2800
- Intel(R) Core(TM) i7-4980HQ CPU @ 2.80GHz - 2800
- Intel(R) Core(TM) i7-4980HQ CPU @ 2.80GHz - 2800
- Intel(R) Core(TM) i7-4980HQ CPU @ 2.80GHz - 2800
- Intel(R) Core(TM) i7-4980HQ CPU @ 2.80GHz - 2800
ENDIANNESS: LE
VERSIONS:
- ares: 1.10.1-DEV
- cldr: 31.0.1
- http_parser: 2.7.0
- icu: 59.1
- modules: 57
- nghttp2: 1.25.0
- node: 8.9.4
- openssl: 1.0.2n
- tz: 2017b
- unicode: 9.0
- uv: 1.15.0
- v8: 6.1.534.50
- zlib: 1.2.11
ERROR Summary:
- broccoliBuilderErrorStack: Error: ENOENT: no such file or directory, open '/Users/xxxxxxxx/development/cfireview/clean-pods/tmp/source_map_concat-input_base_path-i7wWgn1z.tmp/node_modules/firebase/firebase-firestore.js'
at Object.fs.openSync (fs.js:646:18)
at Object.fs.readFileSync (fs.js:551:33)
at SourceMap.addFile (/Users/xxxxxxxx/development/cfireview/clean-pods/node_modules/fast-sourcemap-concat/lib/source-map.js:75:31)
at /Users/xxxxxxxx/development/cfireview/clean-pods/node_modules/broccoli-concat/concat.js:200:16
at Array.forEach (<anonymous>)
at Concat.<anonymous> (/Users/xxxxxxxx/development/cfireview/clean-pods/node_modules/broccoli-concat/concat.js:198:24)
at /Users/xxxxxxxx/development/cfireview/clean-pods/node_modules/fast-sourcemap-concat/lib/source-map.js:419:12
at initializePromise (/Users/xxxxxxxx/development/cfireview/clean-pods/node_modules/rsvp/dist/rsvp.js:567:5)
at new Promise (/Users/xxxxxxxx/development/cfireview/clean-pods/node_modules/rsvp/dist/rsvp.js:1039:33)
at SourceMap.end (/Users/xxxxxxxx/development/cfireview/clean-pods/node_modules/fast-sourcemap-concat/lib/source-map.js:406:10)
- codeFrame: ENOENT: no such file or directory, open '/Users/xxxxxxxx/development/cfireview/clean-pods/tmp/source_map_concat-input_base_path-i7wWgn1z.tmp/node_modules/firebase/firebase-firestore.js'
- errorMessage: Build Canceled: Broccoli Builder ran into an error with `Concat` plugin. π₯
ENOENT: no such file or directory, open '/Users/xxxxxxxx/development/cfireview/clean-pods/tmp/source_map_concat-input_base_path-i7wWgn1z.tmp/node_modules/firebase/firebase-firestore.js'
- errorType: Build Error
- location:
- column: [undefined]
- file: [undefined]
- line: [undefined]
- treeDir: [undefined]
- message: Build Canceled: Broccoli Builder ran into an error with `Concat` plugin. π₯
ENOENT: no such file or directory, open '/Users/xxxxxxxx/development/cfireview/clean-pods/tmp/source_map_concat-input_base_path-i7wWgn1z.tmp/node_modules/firebase/firebase-firestore.js'
- name: Error
- nodeAnnotation: Concat
- nodeName: Concat
- originalErrorMessage: ENOENT: no such file or directory, open '/Users/xxxxxxxx/development/cfireview/clean-pods/tmp/source_map_concat-input_base_path-i7wWgn1z.tmp/node_modules/firebase/firebase-firestore.js'
- stack: Error: ENOENT: no such file or directory, open '/Users/xxxxxxxx/development/cfireview/clean-pods/tmp/source_map_concat-input_base_path-i7wWgn1z.tmp/node_modules/firebase/firebase-firestore.js'
at Object.fs.openSync (fs.js:646:18)
at Object.fs.readFileSync (fs.js:551:33)
at SourceMap.addFile (/Users/xxxxxxxx/development/cfireview/clean-pods/node_modules/fast-sourcemap-concat/lib/source-map.js:75:31)
at /Users/xxxxxxxx/development/cfireview/clean-pods/node_modules/broccoli-concat/concat.js:200:16
at Array.forEach (<anonymous>)
at Concat.<anonymous> (/Users/xxxxxxxx/development/cfireview/clean-pods/node_modules/broccoli-concat/concat.js:198:24)
at /Users/xxxxxxxx/development/cfireview/clean-pods/node_modules/fast-sourcemap-concat/lib/source-map.js:419:12
at initializePromise (/Users/xxxxxxxx/development/cfireview/clean-pods/node_modules/rsvp/dist/rsvp.js:567:5)
at new Promise (/Users/xxxxxxxx/development/cfireview/clean-pods/node_modules/rsvp/dist/rsvp.js:1039:33)
at SourceMap.end (/Users/xxxxxxxx/development/cfireview/clean-pods/node_modules/fast-sourcemap-concat/lib/source-map.js:406:10)
=================================================================================
Exception: "Assertion Failed: You can only unload a record which is not inFlight.
My code:
obj.destroyRecord({
adapterOptions: {
isRealtime: true,
buildReference(db) {
return db.collection('collection1').doc(obj_parent.get('id')).collection('sub_collection1');
}
}
});
My guess is that the firestore adapter unloads the obj
before the server acknowledged the delete.
Stack Trace:
"Error: Assertion Failed: You can only unload a record which is not inFlight. `<obj:9k2j2ogWWg5PybdAkDO9>`
at new EmberError (http://localhost:4200/assets/vendor.js:18152:31)
at Object.assert (http://localhost:4200/assets/vendor.js:17017:23)
at Object.assertAgainstUnloadRecord [as unloadRecord] (http://localhost:4200/assets/vendor.js:105326:30)
at InternalModel.send (http://localhost:4200/assets/vendor.js:111422:30)
at InternalModel.unloadRecord (http://localhost:4200/assets/vendor.js:111175:10)
at Class.unloadRecord (http://localhost:4200/assets/vendor.js:106281:25)
at Class.unloadRecord (http://localhost:4200/assets/vendor.js:114422:12)
at Object.docRef.onSnapshot.docSnapshot [as next] (http://localhost:4200/assets/vendor.js:95498:19)
at next (http://localhost:4200/assets/vendor.js:66261:351333)
at http://localhost:4200/assets/vendor.js:66261:323998"
A declarative, efficient, and flexible JavaScript library for building user interfaces.
π Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. πππ
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google β€οΈ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.