I am working on an app based of Expo - I decided to use firebase as a backend but had come up to a blocker, I need to send push notifications to the users in the app - but Expo doesn't work with Firebase Cloud Messaging (FCM) unless I eject the Expo project and work independently with Android and ios.
To overcome this I decided to store the Expo Notification Tokens in firebase and then write a firebase cloud function in firebase to get all these tokens from the database and trigger a sendPushNotificationAsync() using the expo-server-sdk.
I understand that to do this approach my version of firebase cannot be on the Spark plan - and it isn't.
I decided to implement the solution in TypeScript so I can conform to ES6/ES7 coding standards.
The approach is - I trigger a get request to my firebase function url and this triggers the function to execute. With the code below - when I do a get request against the provided google function URL I get an error:
@firebase/database: FIREBASE WARNING: Exception was thrown by user callback. TypeError: expo.isExpoPushToken is not a function at admin.database.ref.once (/user_code/lib/index.js:24:18) at onceCallback (/user_code/node_modules/firebase-
Is there something I am doing incorrectly it doesn't seem like it is able to initialise and use functions from the Expo import, although I have included this in the package.json to be installed, imported and used.
index.ts - generated by firebase
import * as functions from 'firebase-functions';
import * as admin from 'firebase-admin';
import * as Expo from 'expo-server-sdk';
admin.initializeApp();
// Create a new Expo SDK client
let expo = new Expo();
exports.pushNotifications = functions.https.onRequest((req,res) => {
if(req.method !== 'GET'){
return res.status(403).send('Forbidden!')
}
let allTokens = [];
let messages = [];
admin.database().ref('/all_user_push_tokens/').once('value', (snapshot) => {
if(expo.isExpoPushToken(snapshot.val())){
allTokens.push(snapshot.val())
} else {
console.log(snapshot.val())
}
})
.then(() => {
for (var token in allTokens){
messages.push({
to: token,
sound: 'default',
title: 'NXET',
body: ' NEW ACTIVITIES ADDED!'
})
}
})
.then(() => {
let chunks = expo.chunkPushNotifications(messages)
async (chunks) => {
for (let chunk of chunks) {
try {
await expo.sendPushNotificationsAsync(chunk);
} catch (error){
console.error(error);
}
}
}
return res.status(200).send('SUCCESS - NOTIFICATIONS SENT!!')
})
.catch(() => {
return res.status(403).send('Forbidden!')
});
return res.status(200).send('Function Executing')
})
package.json
{
"name": "functions",
"scripts": {
"build": "tsc",
"serve": "npm run build && firebase serve --only functions",
"shell": "npm run build && firebase functions:shell",
"start": "npm run shell",
"deploy": "firebase deploy --only functions",
"logs": "firebase functions:log"
},
"main": "lib/index.js",
"dependencies": {
"expo-server-sdk": "^2.3.3",
"firebase-admin": "~5.12.0",
"firebase-functions": "^1.0.1"
},
"devDependencies": {
"typescript": "^2.5.3"
},
"private": true
}
Any help would be much appreciated.