Firebase Remote Config allows developers to control the appearance and the behaviour of their apps without having to publish an app update. You can build your app with in-app default configurations and later change those configurations by updating your project’s Remote Config template.
We are happy to announce that you can now manage your Remote Config templates directly from the Admin Node.js SDK.
Typically, you would use the Firebase console to specify and update Remote Config templates manually. However, sometimes you need more automation and server-side control of these settings, such as scheduling Remote Config updates or importing configurations from your own proprietary systems and other Firebase projects. Until now the Remote Config REST API was the only way to implement such use cases, which at times could be cumbersome.
As of version 8.13.0, the Admin SDK introduced a Remote Config API that simplifies the process of creating, accessing, and updating your Remote Config templates from your own backend servers and also from managed Cloud environments like Google Cloud Functions.
Let’s go through some examples on how to use the Firebase Admin Node.js SDK to manage your projects’ templates. You can start by creating a fresh Remote Config template for your project, or you can get the current active template and make changes to it. Here's how you can get the current active template in Node.js:
const admin = require('firebase-admin'); admin.initializeApp(); const template = await admin.remoteConfig().getTemplate(); console.log('ETag from server: ' + template.etag);
Each Remote Config template version is associated with an entity tag (ETag) for version control purposes. The Remote Config API uses this ETag to prevent race conditions and concurrent updates to resources. To learn more about ETags, see ETag - HTTP.
Once you have obtained your current active Remote Config template you can start making modifications. Here are some of the operations you can perform using the Admin Node.js SDK:
Let’s go through an example on adding a new Remote Config condition and a parameter to your template.
// add a new condition template.conditions.push({ name: 'android_en', expression: "device.os == 'android' " + "&& device.country in ['us','uk']", tagColor: 'BLUE' as admin.remoteConfig.TagColor, }); // add a new parameter, that references the above condition template.parameters['header_text'] = { defaultValue: { value: 'A Gryffindor must be brave, talented and helpful.' }, conditionalValues: { 'android_en': { value: 'A Droid must be brave, talented and helpful.' }, }, };
The above example creates a new condition named android_en and uses it in a conditional value of the parameter named header_text. Checkout the documentation to learn more about conditional expressions. Keep in mind that the conditions in a template are listed in descending order by priority. A parameter might have several conditional values associated with it. If multiple conditions evaluate to true, the first condition in the list takes precedence.
android_en
header_text
Once you make updates to your template you must publish it to make the new changes effective. After you publish a Remote Config template using the Firebase Admin Node.js SDK, that template becomes the current active version of your project. Before you publish a template you can always validate it to check for any errors.
try { const validatedTemplate = admin.remoteConfig() .validateTemplate(template); const publishedTemplate = admin.remoteConfig() .publishTemplate(validatedTemplate); } catch(err) { console.log('Error publishing the template:', error); }
For more details and code samples on programmatically modifying Remote Config templates, check out the detailed documentation.
In addition to the API for modifying Remote Config templates, the Firebase Admin Node.js SDK provides an API to manage Remote Config template versions. This API supports the following operations.
The listVersions operation allows you to retrieve a list of metadata for all stored versions of your project, sorted in reverse chronological order. Note that the last 300 versions are stored. All versions that correspond to non-active Remote Config templates (that is, all except the template that is being fetched by clients) are also deleted if they are more than 90 days old. Here’s a sample code to fetch a list of template versions.
listVersions
// list all the Remote Config template Versions // Only the last 300 versions are stored. const listVersionsResult = admin.remoteConfig().listVersions(); listVersionsResult.versions.forEach((version) => { console.log('version', JSON.stringify(version)); });
For a complete list of available operations and examples, check out the documentation on programmatically managing Remote Config template versions.
We hope this new addition of the Remote Config API in the Admin Node.js SDK helps with your backend development tasks. Stay tuned for the Remote Config API to be added across other Firebase Admin SDK platforms. We are excited to see how you use the new APIs in your projects! Hop over to our Github Repo to check out the implementation. Help us further improve our SDKs by providing your valuable feedback, reporting issues, and contributions to our codebase.
The Firebase Admin SDK for Go is now generally available. This is the fourth programming language to join our growing family of Admin SDKs, which already includes support for Java, Python and Node.js. Firebase Admin SDKs enable application developers to programmatically access Firebase services from trusted environments. They complement the Firebase client SDKs, which enable end users to access Firebase from their web browsers and mobile devices. The initial release of the Firebase Admin SDK for Go comes with some Firebase Authentication features: custom token minting and ID token verification.
Similar to the other Firebase Admin SDKs, the Go Admin SDK can be initialized with a variety of authentication credentials and client options. The following code snippet shows how to initialize the SDK using a service account credential obtained from the Firebase console or the Google Cloud console:
import ( "golang.org/x/net/context" firebase "firebase.google.com/go" "google.golang.org/api/option" ) opt := option.WithCredentialsFile("path/to/key.json") app, err := firebase.NewApp(context.Background(), nil, opt)
If you are running your code on Google infrastructure, such as Google App Engine or Google Compute Engine, the SDK can auto-discover application default credentials from the environment. In this case you do not have to explicitly specify any credentials when initializing the Go Admin SDK:
import ( "golang.org/x/net/context" firebase "firebase.google.com/go" ) app, err := firebase.NewApp(context.Background(), nil)
The initial release of the Firebase Admin SDK for Go comes with support for minting custom tokens and verifying Firebase ID tokens. The custom token minting allows you to authenticate users using your own user store or authentication mechanism:
client, err := app.Auth() if err != nil { return err } claims := map[string]interface{}{ "premium": true, "package": "gold", } token, err := client.CustomToken("some-uid", claims)
The resulting custom token can be sent to a client device, where it can be used to initiate an authentication flow using a Firebase client SDK. On the other hand, the ID token verification facilitates securely identifying the currently signed in user on your server:
client, err := app.Auth() if err != nil { return err } decoded, err := client.VerifyIDToken(idToken) uid := decoded.UID
To learn more about using the Firebase Admin SDK for Go, see our Admin SDK setup guide.
We plan to further expand the capabilities of the Go Admin SDK by implementing other useful APIs such as user management and Firebase Cloud Messaging. This SDK is also open source. Therefore we welcome you to browse our Github repo and get involved in the development process by reporting issues and sending pull requests. To all Golang gophers out there, happy coding with Firebase!
Many Firebase developers focus on their apps alone, usually for Android, iOS, or the Web (or all three!). If you're like me, and you spend most of your time on the client side, it can be a hassle to also deal with any backend components. Now that we have Cloud Functions for Firebase, it's super easy and fun to write and deploy backend code in JavaScript without having to manage servers. Personally, my comfort zone is with Android. So, to get acquainted with Cloud Functions, I spent some time brushing up on my JavaScript and learning node.js, which Cloud Functions uses to run backend code.
As part of that period of ramping up, I learned a new way of managing asynchronous work in JavaScript. If you've had experience working with JavaScript in the browser or with Cloud Functions, you may already be familiar with a class called Promise. A promise is a very common way to handle async work. The closest concept for Android developers is the Task API that you sometimes use when dealing with Firebase APIs.
A promise lets you respond to a unit of work that's executing asynchronously, such as a database write or a network request. Cloud Functions understand promises; if you want a function to stay alive during async work, you can do this by returning a promise from the function (except for HTTP/S triggers, which require a response sent to the client). When you return a promise, be sure to return a promise that is "resolved" after all asynchronous work performed in that function is fully complete. Many developers have found this video from the Firebase channel on YouTube very helpful for understanding how promises work with Cloud Functions:
In the video, Jen describes two main ways of dealing with promises. First, there's using the then() method on a promise to chain items of work in sequence, where the next item of work depends on the results from the previous item. Second, there's Promise.all() which creates a new promise that resolves after multiple items of work happening in parallel are all complete. Between these two mechanisms, you can manage most work that normally occurs in a function. When the work is complete, you return the final promise from the function so that the Cloud Functions environment knows when to clean up.
then()
Promise.all()
For simple functions, this works out pretty easily. But many of you (including myself) have discovered that complicated functions can be really difficult to manage when there's a lot of work (with lots of promises) going on. One of the symptoms of mismanaged promises is seeing the following error in the function log in the Firebase console:
Error: read ECONNRESET
This error could mean a few different things. In some cases it could be a bug in a client library. In other cases, it's a symptom of a common mistake when dealing with promises.
If a function is terminated before its network connections are finished, that means those open connections could be forced to close, leaving an ECONNRESET in the log. Here's a situation when that can occur.
ECONNRESET
Imagine you want to start three items of async work, and the work is kicked off in a function called doSomeAsync(), which returns a promise that's resolved upon completion, and you return the promise from the third task like this:
doSomeAsync()
doSomeAsync(x) doSomeAsync(y) return doSomeAsync(z)
Returning a Promise from the function is good. But Cloud Functions needs a promise that resolves when all of the work is fully complete. If we don't have a guarantee that the last item of work will always finish after the other two, then Cloud Functions may clean up the function prematurely, causing problems. Instead, we need to combine all of the promises from all of the work into a new promise that resolves only after all of the others resolve, like this:
const promise_x = doSomeAsync(x) const promise_y = doSomeAsync(y) const promise_z = doSomeAsync(z) return Promise.all([promise_x, promise_y, promise_z])
If you're not tracking every single item of asynchronous work that you kick off in a function, you could see the dreaded ECONNRESET error in your log, and things may not work the way you expect. It really can take some diligence to keep all your promises!
If you want to see an example of a more complicated function, I have an open source tic-tac-toe web game that I wrote for a session I gave at Google I/O '17 that talks about how it was built entirely with Firebase.
For more tutorials and content about Cloud Functions, and other Firebase products, be sure to check out the Firebase channel on YouTube and the Firebase Blog.