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

node-red-contrib-cloud-firestore

v3.2.0

Published

Node-RED nodes to handle google cloud firestore read and write operations.

Downloads

1,205

Readme

node-red-contrib-cloud-firestore

Node-RED nodes to handle google cloud firestore read and write operations.

For any assistance, contributions or stars, visit the repo.

Install

Install from the palette manager

node-red-contrib-cloud-firestore

Install from npm

npm install node-red-contrib-cloud-firestore

Usage

Admin configuration

A configuration property under either Read or Write nodes that initializes a firebase app taking in a name and the json contents of your apps service account credentials which can be generated under Project settings > service accounts > Firebase Admin SDK.

Firestore Read

Node fetches data from a referenced collection, subcollection or document.

Configurations can be made within the node or on the msg.firestore property:

  • collection: [string] The collection or subCollection in reference
  • document: [string] The document reference under the defined collection
  • realtime: [boolean] telling the node to listen for live updates or not (false by default)
  • group: [boolean] fetch all documents under collections with the above supplied collection name (false by default)
  • query: [array<object>] an array of objects defining query methods to apply to the read
  • disableHandler: [boolean] disables the default snapshot handler, returning a built query reference as the payload (false by default)

Response data from the operation is output through the msg.payload property

Upstream input queries

To perform dynamic queries with the read node through input, you need to supply an array of objects on the msg.firestore.query property in the order they will be chained with the query method as the only property and it's value being an array of arguments, or a single string value as show below.

{
  query : [
      {where: ["state", "==", "CA"]},
      {where: ["population", "<", 1000000]}
  ]
}

// reference.where("state", "==", "CA").where("population", "<", 1000000)
{
  query : [
      {orderBy: "name"},
      {limit: 2}
  ]
}

// reference.orderBy("name").limit(2)
{
  query : [
      {where: ["population", ">", 100000]},
      {orderBy: ["population", "asc"]},
      {limit: 2}
  ]
}

// reference.where("population", ">", 100000).orderBy("population", "asc").limit(2)
{
  query : [
      {orderBy: "population"},
      {startAt: 100000},
      {endAt: 1000000}
  ]
}

// reference.orderBy("population").startAt(100000).endAt(1000000)

Custom snapshot handler

You can also write your own snapshot handler under the other settings accordion. The editor is similar to the core function node & but supports the following global objects: config (the nodes settings), snap (query snapshot), util(nodejs), msg, context, RED.util & console. The Promise, Buffer and Date objects are also supported.

The snap object contains the resulting query snapshot.

Do remember that what you return will then be sent as the output payload. The following example returns an array of objects, while logging to the cmd console

const docs = [];
let added = context.flow.get('added');

snap.docChanges().forEach(change => {
    docs.push(change.doc.data());
    if (change.type === 'added') {
      added++;
      console.log('Added: ', change.doc.data());
    }
    if (change.type === 'modified') {
      console.log('Modified: ', change.doc.data());
    }
    if (change.type === 'removed') {
      console.log('Removed: ', change.doc.data());
}
});

context.flow.set('added', added);  
return docs;

Additionally, you can also save your snippets into the snippet library by giving it a file name and clicking the Save to Library button

Realtime edge cases

If you intend on passing in dynamic configurations from an upstream node while still having realtime enabled, the node will not have your upstream values recorded during the next restart. This could result in some unexpected outcomes.

A way around this would be for the node to store your most recent settings from the interface / upstream nodes into node-red's provided storage mechanism.

To enable this workaround in the node, you'll have to change your instances default storage module from memory to localfilesystem in your settings.js file. Read more on this here

Firestore Write

Node performs write operations to the referenced collection, subCollection or document.

Configurations made from within the node or on the msg.firestore property:

  • operation: [string] Write operation to perform, either add, set, update or delete
  • collection: [string] collection or subCollection reference to write to.
  • document: [string] document reference to write to (optional for add operations)
  • options: [object] additional options passed to firebase (currently specific to set operations)

Handling Firestore classes & sentinels

Due to the nature of Cloud firestore's implementation, some actions need special handling.

Arrays

To perform array updates, you'll need to wrap your elements in an object with the _arrayUnion or _arrayRemove property to add or remove elements respectively within an array

msg.payload = {
  animals: {
      _arrayUnion: 'goats'
  },
  farmers: {
      _arrayRemove: {name: "John Doe"}
  }
}

becomes:

msg.payload = {
  animals: firestore.FieldValue.arrayUnion("goats"),
  farmers: firestore.FieldValue.arrayRemove({name: "John Doe"})
}

GeoPoints

Objects within the payload received by the Write Node containing a _lat and _lng property will be replaced with the appropriate GeoPoint class

msg.payload = {
     farm:{
         location: {
              _lat: -1.232134,
              _lng: 36.123131
         },
         fence: [
              {_lat: -1.433434, _lng: 35.123324},
              {_lat: -1.673214, _lng: 36.126541},
              {_lat: -1.334124, _lng: 34.342131}
         ]
    }
}

becomes:

msg.payload = {
  farm: {
      location: new firestore.GeoPoint(-1.232134, 36.123131),
      fence: [
          new firestore.GeoPoint(-1.433434, 35.123324),
          new firestore.GeoPoint(-1.673214, 36.126541),
          new firestore.GeoPoint(-1.334124, 34.342131)
      ]
  }
}

Server Timestamp

Properties with the _serverTimestamp string value will be replace with the appropriate serverTimestamp sentinel

msg.payload = {
  time: '_serverTimestamp'
}

becomes:

msg.payload = {
  time: firestore.FieldValue.serverTimestamp()
}

Increment

Properties with the _increment string value will be replaced with the appropriate increment sentinel

msg.payload = {
  itemCount: {
    '_increment': 30
  }
}

becomes:

msg.payload = {
  itemCount: firestore.FieldValue.increment(30)
}

Delete

Properties with the _delete string value will be replaced with the appropriate delete sentinel

msg.payload = {
  unwantedField: '_delete'
}

becomes:

msg.payload = {
  unwantedField: firestore.FieldValue.delete()
}

Extensibility & additional use cases

Mustache templating

Both the read & write nodes support mustache templating on the collection & document properties, which allows you to cherry pick your collection / document properties directly from the msg object.

For example, setting the collection field to {{col}} with a message object like

msg = {
  col: "users"
}

will have the corresponding node run operations against the users collection.

Firebase instances

Both the read & write nodes can expose a firebase object that contains the current app instance and a reference to the firebase admin sdk, which allows you to extend the node to your liking. Simply enable the eject property in the ui / via an upstream input.

// upstream input / via the ui
msg.firestore = {
 eject: true
};

// output
msg.firebase = {
 "app": "...", // current firebase instance
 "admin": "...", // firebase admin sdk
};

TODO

  • Handle transactions and batch writes