What is the best way to utilize Typescript when making queries to Firebase?

I have successfully integrated push notifications for my app using Firebase Cloud Functions. Now, I am looking to enhance the user experience by updating the app's badge count alongside the push notifications. I understand that this can only be achieved through server-side code and not locally.

My current approach involves retrieving the number of new users from the server and using that number as the badge count in the push notification. However, I am facing challenges in implementing this solution. After spending considerable time trying to figure it out, I am seeking guidance to move forward.

My tech stack includes Firebase functions and Typescript in VSCode. The steps I plan to take are:

  1. Retrieve a list of userIDs from the 'admin' node
  2. Iterate over these userIDs on the 'user' node to check if the user's 'newUser' parameter is true
  3. Compile the results into an array
  4. Calculate the count of new users and use that as the badge count in the push notification

Here is the structure of my 'users' database:

"users": {

  "2NBvNgdNRVe3nccTEDts2Xseboma": {

    "email": "<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="a0d3cfcdc5cfcec5e0d3cfcdc5cfcec58ec3cfcd">[email protected]</a>"

    "newUser": "true",

    "referral": "none",

    ...

  },

  "hjC6os6wzIV1FyULmGxalU3fM7ef": {

    "email": "<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="82f1edefe7edece7c7eef1e7c2f1edefe7edece7ace1edef">[email protected]</a>"

    "newUser": "false",

    "referral": "Bennett",

    ...

  }

And this is how the 'admin' database is set up:

"admin": {

  "2NBvNgdNRVe3nccTEDts2Xseboma": {

    "email": "<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="c6b5a9aba3a9a8a386b5a9aba3a9a8a3e8a5a9ab">[email protected]</a>"

    "familyName": "Someone",

    "memberSince": "1529119893",

  },

  "hjC6os6wzIV1FyULmGxalU3fM7ef": {

    "email": "<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="abd8c4c6cec4c5ceeec7d8ceebd8c4c6cec4c5ce85c8c4c6">[email protected]</a>"

    "familyName": "Someone Else",

    "memberSince": "1529125722",

    ...

  }

Below is the code snippet where I am struggling:

exports.getNewUserCount =

functions.database.ref('/users/{userID}/newUser')

    .onUpdate((snapshot, _context) => {

        console.log('test 2')

        // Get a database reference

        const db = admin.database();
        const ref = db.ref('admin');


        return ref.once('value', function(adminSnap) {

            const userData = adminSnap.val()

            console.log('admin key:', adminSnap.key)
            console.log('user data:', userData)

        })

    });

I am currently stuck at step #1 of retrieving the list of users from the admin node. Any assistance would be greatly appreciated.

UPDATE

After managing to retrieve a snapshot of all users, I am now struggling with iterating over them. How can I convert the snapshot into an array of user keys?

Furthermore, once I have the list of user keys, how do I iterate over the 'users' node to identify the new users (step #2 above)?

Lastly, how can I compile these new users into an array (step #3 above) and calculate the count for the 'badge' parameter in the push notification (step #4 above)?

This process seems inefficient, and I am open to suggestions for improvement. Is there a more streamlined approach to identifying new users without going through the 'admin' node first? Any insights would be valuable as I have been grappling with this for days.

For additional context, I am proficient in Swift, and the app is designed for iOS. Thank you!

UPDATE #2

As an alternative approach, I decided to skip the 'admin' node altogether and directly retrieve a snapshot of all users. Here is the revised code:

const db = admin.database();
const ref = db.ref('users');

return ref.once('value').then((adminSnap) => {

    console.log('admin key:', adminSnap.key)

    // initialize an array to store user data
    let newUserCount = 0;

    // iterate over the snapshot to extract individual user data
    adminSnap.forEach(function (userSnap) {

        const userData = userSnap.val();
        const userKey = userSnap.key

        if (userData.newUser === true) {
            newUserCount++
            console.log('new user:', userKey, userData.newUser, userData.email)
        }
    });

    console.log(newUserCount)
})

While this new code provides the required data for the badge parameter in the push notification, I am concerned about its efficiency. As the database grows, will this approach strain the server and potentially slow down the process? Moreover, could it lead to increased bandwidth costs for my Firebase account?

What started as a simple task has now become quite challenging. I am open to exploring different methods to achieve my goal. Any suggestions would be greatly appreciated. Thank you!

Answer №1

After conducting further research, I decided to scrap my initial approach and opt for a different strategy. My new plan involves creating a fresh node in my Firebase database to store the new user count, which I will then update through code sourced from another location. This method is the most straightforward and will consume the least amount of bandwidth.

Below is the finalized code I came up with:

function sendAlertToiPhone() {

console.log('test E')

// Establish a reference to the database
const db = admin.database();
const ref = db.ref('stats');

ref.child('newUserCount').once('value').then((snapshot) => {

    const newUserCount = snapshot.val()

    console.log('new user count:', newUserCount)

    // dispatch to Phontaine's iPhone 6
    const FCMToken = "blahbehtyblahblah"

    const payload = {
        notification: {
            title: 'New User',
            body: 'Moneypants has a new download.',
            sound: 'default',
            badge: String(newUserCount)
        }
    };

    return admin.messaging().sendToDevice(FCMToken, payload)
        .then(function (response) {
            console.log("Successfully sent message:", response);
        })
        .catch(function (error) {
            console.log("Error sending message:", error);
        });

}).catch(function (err) {
    console.log('new user count error:', err);
})
}

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Exploring the intricacies of Knockout JS mapping nested models using fromJS function

I am struggling with understanding how to effectively utilize the Knockout JS Mapping Plugin. My scenario involves nested models, and currently I am only using the ko.mapping.fromJS() in the parent model. However, I have noticed that the computed values ar ...

Center your attention on an AngularJS-created input element

I'm currently working on a todo list project using AngularJS and I am wondering if there is a method to automatically focus on an input box after creating it by clicking on a button. As of now, the save function in my controller looks like this: $sc ...

When using Mongoose's save function within an async.each loop, it may

While working on an array processing task that involves saving and validating data asynchronously, I encountered an issue with duplicates. Here is the data I'm currently processing: var guests = [{ "email": "<a href="/cdn-cgi/l/email-protection" ...

The placement of the Vuetify tooltip is incorrectly aligned when located in the footer section

Having trouble fixing the issue with the Vuetify tooltip. After scrolling on the page, the tooltip moves up despite using fixed="true". Here is the code snippet causing the problem: <v-footer app inset fixed> <v-row align="center ...

CSS - starting fresh with animations

I am facing an issue with a CSS animation that I created. Everything seems to be working correctly, but I need to complete it by setting the input type to reset the animation. Below is the CSS code snippet that should reset the animation: $('button& ...

What is the technique for invoking methods of the Joi class without the need to instantiate an object?

I recently delved into using the Joi NPM module and found it confusing that although it is described as a class in the documentation, it does not require creating a class object like var joi = new Joi();. Can you explain how this works? My understanding o ...

Describing how to assign multiple variables in a VUEX mutation

store.js import Vue from 'vue'; import Vuex from 'vuex'; import userStore from './user/userStore.js'; import VuexPersist from "vuex-persistedstate"; Vue.use(Vuex) const debug = process.env.NODE_ENV != ...

In C#, transforming JSON serialization to replace single backslashes with double backslashes

When generating JSON to be included directly in an HTML file, it's important to wrap the JSON in a JavaScript string. For example: var dataContacts = '{"Contacts":[{"Id":0,"Active":false,"Company":"Rory The Architect\\, Melt"} ...

Is it possible to convert several XLIFF files of different languages into JSON files using Angular?

I was looking to create a universal logic in a single XLIFF build that would allow access to all languages through JSON files. My goal was to find a way for the code to efficiently load multiple translations within one XLIFF build and execute these transl ...

The initial value for React input is vacant and is not capturing either the state or the prop value

After utilizing Vue for an extended period, I have now transitioned to React. To practice, I am attempting to convert some basic Vue components into React. My initial Vue code was simple as shown below: <template> <div> <h1>Hello { ...

Skipping certain key-value pairs during the conversion from JSON to Excel Worksheet using the XLSX library in JavaScript

I have a set of objects in JSON format within my JavaScript code and I am looking to transform this data into an Excel worksheet. Within the JSON structure, there are certain key-value pairs that I do not wish to include in the Excel output. For instance, ...

Oops! There seems to be an issue with the code: "TypeError: this

I am just starting out with Angular. Currently, I need to assign a method to my paginator.getRangeLabel (I want to use either a standard label or a suffixed one depending on certain conditions): this.paginator._intl.getRangeLabel = this.getLabel; The cod ...

Unplanned pathways on a node-based server

Building a server, I've utilized the following code snippet: function uniqueString(length) { var result = ''; var characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'; for (var i = length; i &g ...

How can I transform this statement into a higher-order function that offers a resource instead of using an object for initialization and destruction?

Starting with this code snippet: convert utilizes svgInjector to start and terminate a resource. export async function convert( serializedSvg: string, svgSourceId: string, containerId: string ): Promise<string> { const svgInjector = new SvgI ...

AngularJS scope variable not getting initialized inside promise

I've encountered an issue with my code while using CartoDB. The goal is to execute a query using their JS library and retrieve some data. The problem arises when I attempt to assign the result as a scope variable in AngularJS, after successfully worki ...

Code that changes every occurrence of a particular filtered selection of HREF values to a different value

When faced with the limitation in Firefox where links cannot be opened in a new tab if they have a HREF tag diverting to a function, it might be necessary to utilize a script to convert them to an actual HREF. Understanding the functionality of foo: func ...

What causes the scrollTop to appear erratic?

There is a simple issue that I find difficult to explain in text, so I have created a video demonstration instead. Please watch the video at this link: The functionality on my page works perfectly when scrolling down, as it replaces images with the next i ...

Switch on and activate a button using AngularJS

I have a set of four buttons that I want to toggle and activate upon clicking them. Currently, the buttons toggle when double-clicked. My desired solution is for the button current btn to be highlighted and display data when clicked, and for the previous ...

Creating HTML content in a new window with Vue.js - a step by step guide

Recently, I encountered a problem with jsPDF regarding Unicode support in table generation. To work around this issue, I decided to utilize the browser's print feature instead. I achieved this by creating a new HTML document with the table and display ...

Using AngularJS, we can create a nested ng-repeat with an expression to filter the

I'm having trouble using a value from the initial ng-repeat as a filter in the nested ng-repeat. The issue lies with {{alpha.value}}. It displays correctly in the first repeat, including the filter and the h3 tag. However, in the second repeat, it s ...