Dialogflow connect to MQTT broker using Firebase? - firebase

I'm trying to use the Cloud Functions for Firebase to make a Dialogflow intent result in an MQTT message being published. I've managed to get the data I needed and all I still am not able to accomplish is:
Establishing a connection to the MQTT broker;
Publishing to said broker.
As the second one requires the former, it is not my concern yet.
The way I see it is: either my code is wrong or MQTT is included in what Firebase calls "external network". And I'm here, mainly, to make sure I don't upgrade to a paid plan for nothing.
index.js:
'use strict';
const functions = require('firebase-functions');
const { WebhookClient, Card, Suggestion } = require('dialogflow-fulfillment');
var mqtt = require('mqtt');
process.env.DEBUG = 'dialogflow:debug';
const HOST = 'broker.mqttdashboard.com';
const PORT = 1883;
const TOPIC = 'topic/voice_recog';
exports.dialogflowFirebaseFulfillment = functions.region('europe-west1').https.onRequest((request, response) => {
const agent = new WebhookClient({ request, response });
try {
function publishParameter(agent) {
let message = agent.parameters.param_test;
return publishToMqtt(message).then((output) => {
agent.add(output);
}).catch(error => {
agent.add('error from publishToMqtt');
});
}
let intentMap = new Map();
intentMap.set('Repeat parameter', publishParameter);
agent.handleRequest(intentMap);
}
catch (err) {
console.error(err);
agent.add(err.message);
agent.send_();
}
});
function publishToMqtt(message) {
console.log("------------------------------");
console.log("Topic: \""+TOPIC+"\"");
console.log("Message: \""+message+"\"");
console.log("------------------------------");
return new Promise((resolve, reject) => {
var options = {
port: PORT,
host: HOST,
clientId: 'mqttjs_' + Math.random().toString(16).substr(2, 8),
keepalive: 60,
reconnectPeriod: 1000,
protocolId: 'MQIsdp',
protocolVersion: 3,
clean: true,
encoding: 'utf8'
};
var client = mqtt.connect("mqtt://"+HOST, {port: PORT});
// is not executed
client.on('connect', function () {
console.log('client connected');
});
// is not executed
client.publish(TOPIC, message, {}, function (err) {
console.log("Tried publishing \""+message+"\" to \""+TOPIC+"\".");
if (err) {
console.log("But the future refused to change:" + err);
reject();
}
else {
resolve(message);
client.end();
clearTimeout(noResp);
}
});
let noResp = setTimeout(() => {
console.log("No connection"); // always gives this result
reject();
client.end();
}, 5000);
});
}
package.json:
{
"name": "assistant-to-mqtt",
"description": "publishes intent parameter to MQTT broker",
"engines": {
"node": "8"
},
"version": "0.0.1",
"private": true,
"scripts": {
"start": "firebase serve --only functions:publish_mqtt",
"deploy": "firebase deploy --only functions:publish_mqtt"
},
"dependencies": {
"actions-on-google": "^2.1.3",
"dialogflow-fulfillment": "^0.4.1",
"firebase-admin": "^5.12.1",
"firebase-functions": "^2.2.1",
"mqtt": "^2.13.0"
}
}
All help is appreciated. Thank you.
EDIT: The log.

You are actually using a MQTT Broker which is treated as an external access URL by Firebase. Try enabling the billing as described here.

Related

Firebase storage-resize-images not triggered by bucket upload

I'm using a Firebase function to upload images to Storage.
I installed the extension firebase/storage-resize-images#0.1.29
When I upload an image directly within the dashboard, the resize happens.
However, images uploaded with my functions do not trigger the resize.
What am I missing here?
async function migrateImageFromURL (folder, url, name, callback) {
const {filePath, fileName} = await downloadRemoteUrlImage(url, name.split('.')[0])
const bucket = admin.storage().bucket();
const destination = `dev/${folder}/${fileName}`;
try {
await bucket.upload(filePath, {
destination: destination,
gzip: true,
metadata: {
fileName,
contentType: `image/${fileName.split('.')[1]}`,
cacheControl: 'public, max-age=31536000',
},
});
callback(destination)
}
catch (e) {
throw new Error("uploadLocalFileToStorage failed: " + e);
}
return ''
};
Create a cloud function with busyboy
Create a sample firebase function
Copy the code for package.json
Run the command to install the node modules
npm run
Copy the code for index.js
To generate a private key file for your service account:
In the Firebase console, open Settings > Service Accounts.
Click Generate New Private Key, then confirm by clicking Generate Key.
Choose Node Js
Securely store the JSON file containing the key.
Copy the firebase-admin-sdk.json file inside the function directory
Deploy the function to firebase
firebase deploy --only functions
Get the http endpoint from the firebase console
Index.js
const functions = require("firebase-functions");
const os = require("os");
const path = require("path");
const spawn = require("child-process-promise").spawn;
//To enable Cross AXIS
//Change to False to avoid DDOS
const cors = require("cors")({ origin: true });
//Parse Files
const Busboy = require("busboy");
//Files System
const fs = require("fs");
var gcconfig = {
// Get the project ID from firebaserc
projectId: "<project_id>",
// Write the name of the file in the root director which contains the private key of firebase-admin-sdk
keyFilename: "firebase-admin-sdk.json"
};
// const gcs = require("#google-cloud/storage")(gcconfig);
const {Storage} = require('#google-cloud/storage');
const gcs = new Storage(gcconfig);
exports.uploadFile = functions.https.onRequest((req, res) => {
//Allowing CROSS SITE
cors(req, res, () => {
if (req.method !== "POST") {
return res.status(500).json({
message: "Not allowed"
});
}
console.log("Starting BusBOY");
const busboy = Busboy({ headers: req.headers});
let uploadData = null;
//File parsing
busboy.on("file", (fieldname, file, filename, encoding, mimetype) => {
// Firebase cloudfunction will have some tmpdirectory tmpdir
// It will be cleaned up after execution
console.log("File function reached ");
console.log("Temp folder is "+os.tmpdir());
console.log("File name is "+filename.filename);
const filepath = path.join(os.tmpdir(),filename.filename);
console.log("Location of file is "+filepath);
uploadData = { file: filepath, type: mimetype };
console.log("Writing to temp file storage");
//Writing file to storage
file.pipe(fs.createWriteStream(filepath));
//Extra Details such as limit error
file.on('limit', () => {
console.log("Reached size limit");
debugLog(options, `Size limit reached for ${field}->${filename.filename}, bytes:${getFilesizeInBytes(filename)}`);
});
file.on('end', () => {
const size = getFilesizeInBytes(filename.filename);
console.log("File size is "+size+" bytes");
});
file.on('error', (err) => {
console.log("File format error");
});
});
//For Form data Listener
// busboy.on("field",()=>{
// });
// Finishes the whole process, only upload after that
busboy.on("finish", () => {
// Firebase storage, Inside the console itself
// Copy the folder location
// gs://<Project_id>.appspot.com
// Remove the gs String
console.log("Finished BusBoy");
var your_project_id="<your_project_id>.appspot.com";
const bucket = gcs.bucket(your_project_id);
console.log("Uploading Image to firebase");
bucket
.upload(uploadData.file, {
uploadType: "media",
metadata: {
metadata: {
contentType: uploadData.type
}
}
})
.then(() => {
// Success
console.log("Uploaded Successfully");
res.status(200).json({
message: "It worked!"
});
})
.catch(err => {
// Error
console.log("Error while uploading");
res.status(500).json({
error: err
});
});
});
//End the parsing
console.log("End Parsing");
busboy.end(req.rawBody);
});
});
//Finding the file size from the filename
function getFilesizeInBytes(filename) {
var stats = fs.statSync(filename);
var fileSizeInBytes = stats.size;
return fileSizeInBytes;
}
package.json
{
"name": "functions",
"description": "Cloud Functions for Firebase",
"scripts": {
"serve": "firebase emulators:start --only functions",
"shell": "firebase functions:shell",
"start": "npm run shell",
"deploy": "firebase deploy --only functions:uploadFile",
"logs": "firebase functions:log"
},
"engines": {
"node": "14"
},
"main": "index.js",
"dependencies": {
"firebase-admin": "^9.8.0",
"firebase-functions": "^3.14.1",
"#google-cloud/storage": "^6.0.1",
"busboy": "^1.6.0",
"child-process-promise": "^2.2.1",
"cors": "^2.8.5"
},
"devDependencies": {
"firebase-functions-test": "^0.2.0"
},
"private": true
}
For more details
Checkout https://github.com/katmakhan/firebase-course/tree/master/Firebase%20Cloud%20Function/Image%20Uploader

How to upload files to firebase storage using rest api in unity

I want to upload files to firebase storage using the rest API from unity. It is like clicking the browse button, browsing on local storage, selecting files, and then uploading.
How do I do this?
Create a cloud function with busyboy
Create a sample firebase function
Copy the code for package.json
Run the command to install the node modules
npm run
Copy the code for index.js
To generate a private key file for your service account:
In the Firebase console, open Settings > Service Accounts.
Click Generate New Private Key, then confirm by clicking Generate Key.
Choose Node Js
Securely store the JSON file containing the key.
Copy the firebase-admin-sdk.json file inside the function directory
Deploy the function to firebase
firebase deploy --only functions
Get the http endpoint from the firebase console
Index.js
const functions = require("firebase-functions");
const os = require("os");
const path = require("path");
const spawn = require("child-process-promise").spawn;
//To enable Cross AXIS
//Change to False to avoid DDOS
const cors = require("cors")({ origin: true });
//Parse Files
const Busboy = require("busboy");
//Files System
const fs = require("fs");
var gcconfig = {
// Get the project ID from firebaserc
projectId: "<project_id>",
// Write the name of the file in the root director which contains the private key of firebase-admin-sdk
keyFilename: "firebase-admin-sdk.json"
};
// const gcs = require("#google-cloud/storage")(gcconfig);
const {Storage} = require('#google-cloud/storage');
const gcs = new Storage(gcconfig);
exports.uploadFile = functions.https.onRequest((req, res) => {
//Allowing CROSS SITE
cors(req, res, () => {
if (req.method !== "POST") {
return res.status(500).json({
message: "Not allowed"
});
}
console.log("Starting BusBOY");
const busboy = Busboy({ headers: req.headers});
let uploadData = null;
//File parsing
busboy.on("file", (fieldname, file, filename, encoding, mimetype) => {
// Firebase cloudfunction will have some tmpdirectory tmpdir
// It will be cleaned up after execution
console.log("File function reached ");
console.log("Temp folder is "+os.tmpdir());
console.log("File name is "+filename.filename);
const filepath = path.join(os.tmpdir(),filename.filename);
console.log("Location of file is "+filepath);
uploadData = { file: filepath, type: mimetype };
console.log("Writing to temp file storage");
//Writing file to storage
file.pipe(fs.createWriteStream(filepath));
//Extra Details such as limit error
file.on('limit', () => {
console.log("Reached size limit");
debugLog(options, `Size limit reached for ${field}->${filename.filename}, bytes:${getFilesizeInBytes(filename)}`);
});
file.on('end', () => {
const size = getFilesizeInBytes(filename.filename);
console.log("File size is "+size+" bytes");
});
file.on('error', (err) => {
console.log("File format error");
});
});
//For Form data Listener
// busboy.on("field",()=>{
// });
// Finishes the whole process, only upload after that
busboy.on("finish", () => {
// Firebase storage, Inside the console itself
// Copy the folder location
// gs://<Project_id>.appspot.com
// Remove the gs String
console.log("Finished BusBoy");
var your_project_id="<your_project_id>.appspot.com";
const bucket = gcs.bucket(your_project_id);
console.log("Uploading Image to firebase");
bucket
.upload(uploadData.file, {
uploadType: "media",
metadata: {
metadata: {
contentType: uploadData.type
}
}
})
.then(() => {
// Success
console.log("Uploaded Successfully");
res.status(200).json({
message: "It worked!"
});
})
.catch(err => {
// Error
console.log("Error while uploading");
res.status(500).json({
error: err
});
});
});
//End the parsing
console.log("End Parsing");
busboy.end(req.rawBody);
});
});
//Finding the file size from the filename
function getFilesizeInBytes(filename) {
var stats = fs.statSync(filename);
var fileSizeInBytes = stats.size;
return fileSizeInBytes;
}
package.json
{
"name": "functions",
"description": "Cloud Functions for Firebase",
"scripts": {
"serve": "firebase emulators:start --only functions",
"shell": "firebase functions:shell",
"start": "npm run shell",
"deploy": "firebase deploy --only functions:uploadFile",
"logs": "firebase functions:log"
},
"engines": {
"node": "14"
},
"main": "index.js",
"dependencies": {
"firebase-admin": "^9.8.0",
"firebase-functions": "^3.14.1",
"#google-cloud/storage": "^6.0.1",
"busboy": "^1.6.0",
"child-process-promise": "^2.2.1",
"cors": "^2.8.5"
},
"devDependencies": {
"firebase-functions-test": "^0.2.0"
},
"private": true
}
For more details
Checkout https://github.com/katmakhan/firebase-course/tree/master/Firebase%20Cloud%20Function/Image%20Uploader

Code problem in DialogFlow Fulfillment as it does not recognize Firebase asynchronous functions

I'm having problems because the code I made in the DialogFlow Fulfillment index.js when I took the context parameters he was unable to send talking to the DialogFlow support I was informed that the DialogFlow Fulfillment does not recognize asynchronous functions so when I use the "push" from Firebase to send the parameters he doesn't send anything I believe he expects some parameter from the context but because he doesn't receive it he skips the push function and ends up not executing and doesn't send anything.
DialogFlow Fulfillment index.js code:
const functions = require('firebase-functions');
const { WebhookClient } = require('dialogflow-fulfillment');
const { Card, Suggestion } = require('dialogflow-fulfillment');
const admin = require('firebase-admin');
admin.initializeApp({
credential: admin.credential.applicationDefault(),
databaseURL: 'https://testechatbot-2020.firebaseio.com/'
});
process.env.DEBUG = 'dialogflow:debug';
exports.dialogflowFirebaseFulfillment = functions.https.onRequest((request, response) => {
const agent = new WebhookClient({ request, response });
console.log('Dialogflow Request headers: ' + JSON.stringify(request.headers));
console.log('Dialogflow Request body: ' + JSON.stringify(request.body));
function Mensagem(agent) {
var context = agent.context.get('awainting_nome');
var nome = context.parameters.nome;
var mensagem = agent.parameters.mensagem;
let teste = nome + " " + mensagem;
try {
admin.database().ref('Dados/').push({
Nome: nome,
Mensagem: mensagem
});
} catch (err) {
console.error(err);
return;
}
}
let intentMap = new Map();
intentMap.set('EntradaMensagem', Mensagem);
agent.handleRequest(intentMap);
});
DialogFlow Fulfillment package.json code:
{
"name": "dialogflowFirebaseFulfillment",
"description": "Fluxo com envio de parametros para o Firebase",
"version": "1.0.0",
"private": true,
"license": "Apache Version 2.0",
"author": "Google Inc.",
"esversion": 8,
"engines": {
"node": ">=10.0.0"
},
"scripts": {
"start": "firebase serve",
"deploy": "firebase deploy"
},
"dependencies": {
"#google-cloud/firestore": "^0.16.1",
"firebase-admin": "^8.13.0",
"actions-on-google": "^2.2.0",
"firebase-functions": "^3.7.0",
"dialogflow": "^1.2.0",
"dialogflow-fulfillment": "^0.6.0",
"#google-cloud/dialogflow": "^3.0.0",
"node-fetch": "^2.6.0"
}
}
Image with response from DialogFlow support about asynchronous functions
response from DialogFlow support
I'm not sure where you heard that the Intent Handler can't support async functions. They most certainly can. If you're using an async function (or a function that returns a Promise - same thing), you either must declare it an async function or return the Promise.
Your handler function should look something more like
function Mensagem(agent) {
var context = agent.context.get('awainting_nome');
var nome = context.parameters.nome;
var mensagem = agent.parameters.mensagem;
let teste = nome + " " + mensagem;
return admin.database().ref('Dados/').push({
Nome: nome,
Mensagem: mensagem
})
.then( snapshot => {
agent.add( "pushed" );
})
.catch (err => {
console.error(err);
agent.add( "Error." );
})
}

Firestore automatic backup using cloud functions?

Firebase docs recommends that you deploy an App Engine application to handle automatic firestore exports.
https://firebase.google.com/docs/firestore/solutions/schedule-export
app.js
const axios = require('axios');
const dateformat = require('dateformat');
const express = require('express');
const { google } = require('googleapis');
const app = express();
// Trigger a backup
app.get('/cloud-firestore-export', async (req, res) => {
const auth = await google.auth.getClient({
scopes: ['https://www.googleapis.com/auth/datastore']
});
const accessTokenResponse = await auth.getAccessToken();
const accessToken = accessTokenResponse.token;
const headers = {
'Content-Type': 'application/json',
Authorization: 'Bearer ' + accessToken
};
const outputUriPrefix = req.param('outputUriPrefix');
if (!(outputUriPrefix && outputUriPrefix.indexOf('gs://') == 0)) {
res.status(500).send(`Malformed outputUriPrefix: ${outputUriPrefix}`);
}
// Construct a backup path folder based on the timestamp
const timestamp = dateformat(Date.now(), 'yyyy-mm-dd-HH-MM-ss');
let path = outputUriPrefix;
if (path.endsWith('/')) {
path += timestamp;
} else {
path += '/' + timestamp;
}
const body = {
outputUriPrefix: path
};
// If specified, mark specific collections for backup
const collectionParam = req.param('collections');
if (collectionParam) {
body.collectionIds = collectionParam.split(',');
}
const projectId = process.env.GOOGLE_CLOUD_PROJECT;
const url = `https://firestore.googleapis.com/v1beta1/projects/${projectId}/databases/(default):exportDocuments`;
try {
const response = await axios.post(url, body, { headers: headers });
res
.status(200)
.send(response.data)
.end();
} catch (e) {
if (e.response) {
console.warn(e.response.data);
}
res
.status(500)
.send('Could not start backup: ' + e)
.end();
}
});
// Index page, just to make it easy to see if the app is working.
app.get('/', (req, res) => {
res
.status(200)
.send('[scheduled-backups]: Hello, world!')
.end();
});
// Start the server
const PORT = process.env.PORT || 6060;
app.listen(PORT, () => {
console.log(`App listening on port ${PORT}`);
console.log('Press Ctrl+C to quit.');
});
package.json
{
"name": "solution-scheduled-backups",
"version": "1.0.0",
"description": "Scheduled Cloud Firestore backups via AppEngine cron",
"main": "app.js",
"engines": {
"node": "8.x.x"
},
"scripts": {
"deploy": "gcloud app deploy --quiet app.yaml cron.yaml",
"start": "node app.js"
},
"author": "Google, Inc.",
"license": "Apache-2.0",
"dependencies": {
"axios": "^0.18.0",
"dateformat": "^3.0.3",
"express": "^4.16.4",
"googleapis": "^38.0.0"
},
"devDependencies": {
"prettier": "^1.16.4"
}
}
cron.yaml
cron:
- description: "Daily Cloud Firestore Export"
url: /cloud-firestore-export?outputUriPrefix=gs://BUCKET_NAME[/PATH]&collections=test1,test2
target: cloud-firestore-admin
schedule: every 24 hours
QUESTION
But I was wondering, is it possible to achieve the same thing with an HTTP cloud function and the Cloud Scheduler ?
Is there anything in this App Engine code that I couldn't reproduce or access with an HTTP cloud function? I mean, is the App Engine project really necessary here?
NOTE: This is not an opinion-based question, nor it's too broad. I want to know if I need the App Engine to achieve this behavior or not, and why.
I wouldn't need to set it as an express server, obviously. Just a normal HTTP cloud function, that when called, does the exporting.
I would add something like the following cron job into the Cloud Scheduler:
You will not need App Engine at all if you use Cloud Scheduler to trigger a function that does the backup.

Amazon Lambda to Firebase

I get 'Cannot find module 'firebase' when I try to run this in Lambda (Node.js 4.3)
var Firebase = require('firebase');
Same thing happens when I try to upload a zipped package that includes node_modules/firebase
Does anybody have a working 'write from lambda to firebase' implementation?
To safely use firebase npm package (version 3.3.0) in AWS Lambda (Nodejs 4.3), Please do the following:
'use strict';
var firebase = require("firebase");
exports.handler = (event, context, callback) => {
context.callbackWaitsForEmptyEventLoop = false; //<---Important
var config = {
apiKey: "<<apikey>>",
authDomain: "<<app_id>>.firebaseapp.com",
databaseURL: "https://<<app_id>>.firebaseio.com",
storageBucket: "<<app_id>>.appspot.com",
};
if(firebase.apps.length == 0) { // <---Important!!! In lambda, it will cause double initialization.
firebase.initializeApp(config);
}
...
<Your Logic here...>
...
};
I solved my problem by using firebase REST api
var https = require('https');
exports.handler = function(event, context, callback) {
var body = JSON.stringify({
foo: "bar"
})
var https = require('https');
var options = {
host: 'project-XXXXX.firebaseio.com',
port: 443,
path: '/.json',
method: 'POST'
};
var req = https.request(options, function(res) {
console.log(res.statusCode);
res.on('data', function(d) {
process.stdout.write(d);
});
});
req.end(body);
req.on('error', function(e) {
console.error(e);
});
callback(null, "some success message");
}
This is late, but in case someone else is looking:
Zipping your project folder instead of the contents of the project folder can cause this. The zipped folder, when extracted, should not contain a folder with the lambda files in it, but should have the index.js file and the node_modules folder at root level.
A working example of a lambda function is (using latest shiny firebase stuff *sigh*):
var firebase = require('firebase');
// Your service account details
var credentials = {
"type": "service_account",
"project_id": "project-123451234512345123",
"private_key_id": "my1private2key3id",
"private_key": "-----BEGIN PRIVATE KEY-----InsertKeyHere-----END PRIVATE KEY-----\n",
"client_email": "projectname#project-123451234512345123.iam.gserviceaccount.com",
"client_id": "1111222223333344444",
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
"token_uri": "https://accounts.google.com/o/oauth2/token",
"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
"client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/projectname%40project-123451234512345123.iam.gserviceaccount.com"
};
firebase.initializeApp({
serviceAccount: credentials,
databaseURL: "https://project-123451234512345123.firebaseio.com"
});
exports.handler = function (event, context, callback) {
// I use some data passed in from AWS API Gateway:
if (!event.firebaseUid) {
callback('Missing param for id');
}
firebase.database().ref().child('users').child(firebaseUid).child('at').set(newTokens.access_token).then(function (data) {
console.log('Firebase data: ', data);
firebase.database().goOffline();
callback(null, 'Firebase data: ', data);
}).catch(function (error) {
callback('Database set error ' + error);
});
};
Now for the caveat. I have experienced this causing the lambda function to timeout even after the firebase callback has happened, ie. the set function seems to create a listener that holds the lambda function open despite return of correct data.
Update: Calling firebase.database().goOffline() fixes the Lambda function timeout issue i was experiencing.
The usual cautions about security not being verified or appropriate, and the possibilities of halting space and time by using this apply.
2017-03-22 edit: google just announced firebase cloud functions, which is a much better way to do this. Cloud functions work just like lambda, and can trigger from firebase events.
Here's my solution using the REST api (so you don't need to require anything):
var https = require('https');
var firebaseHost = "yourapp.firebaseio.com";
function fbGet(key){
return new Promise((resolve, reject) => {
var options = {
hostname: firebaseHost,
port: 443,
path: key + ".json",
method: 'GET'
};
var req = https.request(options, function (res) {
res.setEncoding('utf8');
var body = '';
res.on('data', function(chunk) {
body += chunk;
});
res.on('end', function() {
resolve(JSON.parse(body))
});
});
req.end();
req.on('error', reject);
});
}
function fbPut(key, value){
return new Promise((resolve, reject) => {
var options = {
hostname: firebaseHost,
port: 443,
path: key + ".json",
method: 'PUT'
};
var req = https.request(options, function (res) {
console.log("request made")
res.setEncoding('utf8');
var body = '';
res.on('data', function(chunk) {
body += chunk;
});
res.on('end', function() {
resolve(body)
});
});
req.end(JSON.stringify(value));
req.on('error', reject);
});
}
You can use it like this:
fbPut("/foo/bar", "lol").then(res => {
console.log("wrote data")
})
And then:
fbGet("/foo/bar").then(data => {
console.log(data); // prints "lol"
}).catch(e => {
console.log("error saving to firebase: ");
console.log(e);
})
Another alternative if you're using a node-based development setup is to use the node-lambda package from here. Essentially it provides wrappers to set up, test and deploy to lambda. node-lambda deploy will package up any modules you've installed (e.g. with npm i --save firebase) and make sure they're available on Lambda itself. I've found it really helpful for managing external modules.
For me firebase-admin should do the trick.
https://firebase.google.com/docs/admin/setup
Thanks for Josiah Choi for suggesting context.callbackWaitsForEmptyEventLoop though. So lambda doesn't need to initializeFirebase everytimes. My first run was really slow.
var firebase = require('firebase-admin');
module.exports.Test = (event, context, callback) => {
context.callbackWaitsForEmptyEventLoop = false; //<---Important
if(firebase.apps.length == 0) { // <---Important!!! In lambda, it will cause double initialization.
firebase.initializeApp({
credential: firebase.credential.cert("serviceAccount.json"),
databaseURL: <YOUR FIREBASE URL>
});
}
firebase.database().ref('conversation').once('value').then(function(snapshot) {
console.log (snapshot.val()) ;
var bodyReturn = {
input: snapshot.val()
} ;
callback(null,bodyReturn);
context.succeed() ;
});
};
After trying a few things, this seems to work for me (v 3.10.8) :
for(var i=0;i<5;i++)
{
var firebase = require('firebase');
var config = {
apiKey: "",
authDomain: "",
databaseURL: "",
storageBucket: "",
messagingSenderId: ""
};
if(firebase.apps)
if(firebase.apps.length==0)
firebase.initializeApp(config)
firebase.database().ref().child("test").once('value').
then(function(snapshot) {
console.log(snapshot.val());
});
}

Resources