npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

ember-firebase-adapter

v0.0.1

Published

Unofficial Ember Adapter and Serializer for Firebase

Downloads

2

Readme

ember-firebase-adapter

Unofficial Ember Adapter and Serializer for Firebase

Installation

Download the addon by running this command:

ember install ember-firebase-adapter

Setup your application adapter like this:

// app/adapters/application.js
import Firebase from 'ember-firebase-adapter/adapters/firebase';

export default Firebase.extend({
  // DEFAULT: _innerPath
  innerPathName: <name_of_choice>
});

This addon has a dependency with EmberFire.

Features

Fan-out

When saving a or deleting a record, we can include other paths to be updated alongside it.

// Saving
this.get('store').createRecord('comment', {
  message: 'Foo'
}).save({
  adapterOptions: {
    include: {
      'feeds/user_a/:id': true,
      'feeds/user_b/:id': true
    }
  }
});

// Deleting
this.get('store').findRecord('comment', 'comment_a').then((comment) => {
  comment.deleteRecord();

  comment.save({
    adapterOptions: {
      include: {
        [`feeds/user_a/${comment.get('id')}`]: null,
        [`feeds/user_b/${comment.get('id')}`]: null
      }
    }
  });
});

// Destroy
this.get('store').findRecord('comment', 'comment_a').then((comment) => {
  comment.destroyRecord({
    adapterOptions: {
      include: {
        [`feeds/user_a/${comment.get('id')}`]: null,
        [`feeds/user_b/${comment.get('id')}`]: null
      }
    }
  });
});

Notice the :id keyword in the createRecord example above. This will be replaced by the record's ID.

Saving with path

When saving a record, you can provide a path to where you want it to be saved.

this.get('store').createRecord('comment', {
  message: 'Foo'
}).save({
  adapterOptions: {
    path: 'foo/bar'
  }
})

If no path is provided, it defaults to the pluralized name of the model.

Only changed attributes gets updated

This way, we can now have rules that doesn't allow some attributes to be edited.

However, there's a caveat to this. Relationships aren't considered attributes so Ember Data currently doesn't provide us a way to know if a relationship has changed. As a workaround, we can include the relationship as part of our fan-out when saving the record.

const user = this.get('store').peekRecord('user', 'user_a');
const comment = this.get('store').peekRecord('comment', 'comment_a');

comment.set('message', 'Foo');
comment.set('author', user);

comment.save({
  adapterOptions: {
    include: {
      [`comments/${comment.get('id')}/author`]: user.get('id')
    }
  }
});

You can see now that we have control on what the value of our relationship references would be. This will be useful for simple hasMany relationships where the default value was true in EmberFire.

Retrieving records with path

When retrieving a record, you can provide a path to where you want it to be fetched from.

this.get('store').findRecord('comment', 'comment_a', {
  adapterOptions: {
    path: 'foo/bar'
  }
});

Queries

The query params here uses the same format as the one in EmberFire with additional support to the following:

  • orderBy: '.value'.
  • path - Path to query the data from
  • referencedTo - Path of where the record itself will exist (see example below)

For our example, let's assume the following data structure.

{
  "chatrooms": {
    "one": {
      "title": "Historical Tech Pioneers",
      "lastMessage": "ghopper: Relay malfunction found. Cause: moth.",
      "timestamp": 1459361875666
    },
    "two": { ... },
    "three": { ... }
  },

  "members": {
    "one": {
      "ghopper": true,
      "alovelace": true,
      "eclarke": true
    },
    "two": { ... },
    "three": { ... }
  },

  "messages": {
    "one": {
      "m1": {
        "name": "eclarke",
        "message": "The relay seems to be malfunctioning.",
        "timestamp": 1459361875337
      },
      "m2": { ... },
      "m3": { ... }
    },
    "two": { ... },
    "three": { ... }
  },

  "users": {
    "ghopper": {
      "name": "Grasshopper",
      "photoUrl": "photo.jpg"
    },
    "alovelace": { ... },
    "eclarke": { ... }
  }
}

To fetch the chatroom members, use a combination of path and referencedTo.

this.get('store').query('user', {
  path: 'members/one',
  referencedTo: 'users',
  limitToFirst: 10
});

To fetch the chatroom messages, simply use path without any referencedTo.

this.get('store').query('message', {
  path: 'messages/one',
  limitToFirst: 10
});

Inner path

If your model is deeply nested like comments/group_a/post_a/comment_a, it may be useful in some cases to be able to determine it's inner path. To do this, we need to set a model attribute of _innerPath: attr('string') like this:

// app/models/comment
import Model from 'ember-data/model';
import attr from 'ember-data/attr';

export default Model.extend({
  title: attr('string'),
  _innerPath: attr('string'),
});

Calling comment.get('_innerPath') will now return group_a/post_a. Take note that this is just a client-side only property. The _innerPath won't be saved in your Firebase DB.

Changing the inner path key name

If you prefer a different name other than _innerPath, set the innerPathName value to your desired attribute name in your adapter.

Timestamp transform

Timestamp transform is provided as a convenience to firebase.database.ServerValue.TIMESTAMP.

// app/models/comment
import Model from 'ember-data/model';
import attr from 'ember-data/attr';

export default Model.extend({
  title: attr('string'),
  timestamp: attr('timestamp'),
});

Whenever we create a new record, we can simply set timestamp to any value that we want (e.g. new Date()). Once the timestamp from Firebase server is available, it'll update the value appropriately in a JavaScript Date instance.

Caveats

  • Relationships doesn't automatically save. See explanation.
  • store.query() won't listen for child added/removed records. This is because as of Ember Data 2.15, they don't provide us any Adapter level way to manipulate the query result.

Developing

Installation

  • git clone <repository-url> this repository
  • cd ember-firebase-adapter
  • npm install

Running

Running Tests

  • npm test (Runs ember try:each to test your addon against multiple Ember versions)
  • ember test
  • ember test --server

Building

  • ember build

For more information on using ember-cli, visit https://ember-cli.com/.