Skip to content

Makes firestore requests using the Google REST API to avoid the gRPC cold start issue.

Notifications You must be signed in to change notification settings

samcorcos/firestore-rest

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

21 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Firestore REST

npm version npm version

Due to an issue with gRPC, any request that involves Firestore in conjunction with Firebase Functions with take 5-10 seconds to respond after a deploy.

For more information about this particular issue, see this ticket.

As of February 2019, if you want your Firestore requests to respond in less than 5-10 seconds after a deploy, you have to use the REST API provided by googleapis.

This package wraps the googleapis class for Firestore in a way that is easier to use.

Hopefully, when this ticket is resolved, this package will no longer be necessary, but according to Google support, this might be a persistent issue until late 2019. Until then, you should be able to use this package without much downside.

https://cloud.google.com/firestore/docs/reference/rest/v1/projects.databases.documents

Set up

npm i --save firestore-rest

You will need to ensure that you have GOOGLE_APPLICATION_CREDENTIALS and GCLOUD_PROJECT as environment variables. The former is the path to your .json credentials file, and the latter is the project name.

NOTE: I found that I had to export these within the function because Firebase Functions does not allow upper-case variable names for some reason. If you try to do so, you'll get the following error:

Error: Invalid config name onCadenceAssignToContact.GOOGLE_APPLICATION_CREDENTIALS, cannot use upper case.

So my firebase initialization file has this at the top:

process.env.GOOGLE_APPLICATION_CREDENTIALS = path.join(__dirname, '../path/to/credentials.json')
process.env.GCLOUD_PROJECT = 'my-app-name'

These aren't secret, so it doesn't really matter how you pass those values to the API.

Usage

When initializing firebase-admin, initialize and export db as well. See example below for one way to configure your app:

const admin = require('firebase-admin')
const Firestore = require('firestore-rest')
const path = require('path')

process.env.GOOGLE_APPLICATION_CREDENTIALS = path.join(__dirname, '../path/to/credentials.json')
process.env.GCLOUD_PROJECT = 'my-app-name'

var serviceAccount = require('../path/to/credentials.json')

admin.initializeApp({
  credential: admin.credential.cert(serviceAccount),
  databaseURL: 'https://<your app>.firebaseio.com'
})

// const db = admin.firestore() <= this is the old way to do it
const db = new Firestore()

module.exports = {
  admin,
  db
}

Then you can use the function the same way you would otherwise, as this package transforms the results to be backwards-compatible. For example:

// get
const getSome = async () => {
  try {
    const response = await db.collection('users').doc('12312312421321').get()
    console.info(response)
  } catch (err) {
    console.error(err)
  }
}

// set
const setSome = async () => {
    try {
        const response = await db.collection('users').doc('foo').set({ email: 'user@example.com' })
        console.log(response.writeTime.toDate())
    } catch (err) {
        console.error(err)
    }
}

// where
const setSome = async () => {
    try {
        const response = await db.collection('users').where('email', '==', 'user@example.com').where('name', '>=', 'foo').get()
        response.forEach(user => {
            console.log(user.data())
        })
        console.log(response.writeTime.toDate())
    } catch (err) {
        console.error(err)
    }
}

About

Makes firestore requests using the Google REST API to avoid the gRPC cold start issue.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published