how to use firebase storage bucket node sdk - node.js

the code is super simple
const sharp = require('sharp');
const admin = require('firebase-admin');
const fecha = require('fecha');
admin.initializeApp({
serviceAccountId: '<service-account>.iam.gserviceaccount.com',
databaseURL: "<database-url>",
storageBucket: "<storage-bucket>",
projectId: "<project-id>"
});
const storage = admin.storage();
// console.log(storage.bucket().ref('/general/reviews/1/test.jpg'));
console.log(storage.ref('/general/reviews/1/file.txt').putString('casacasacasa'));
i put this code into a cloud function but it crashes
storage.bucket(...).ref is not a function at exports.madrid (/workspace/index.js:666:30) at process.nextTick (/layers/google.nodejs.functions-framework/functions-framework/node_modules/#google-cloud/functions-framework/build/src/invoker.js:100:17) at process._tickCallback (internal/process/next_tick.js:61:11)
and if i uncomment the first line it goes
TypeError: storage.ref is not a function at exports.madrid (/workspace/index.js:666:21) at process.nextTick (/layers/google.nodejs.functions-framework/functions-framework/node_modules/#google-cloud/functions-framework/build/src/invoker.js:100:17) at process._tickCallback (internal/process/next_tick.js:61:11)
i'm 100% the bucket exists and this very same code on the android sdk works fine...
what am i doing wrong?

Take care if you use firebase-admin for storage you have to follow the documentation : https://googleapis.dev/nodejs/storage/latest/
With firebase-admin the ref function is replace by file like this :
admin.storage().bucket().file(remotePath).save(buffer)

Related

Firestore simple node script on pc doesn't work even though same code runs perfectly on firebase functions

Hello I am running a small script that I want to run locally since max timeout of firebase functions is 9 minutes and that is not enough for me (I have to run a large scale update on data types).
So the code is basically:
const admin = require('firebase-admin');
admin.initializeApp();
const db = admin.firestore();
db.collection('users')
.get()
.then(querySnapshot => {
querySnapshot.docs.forEach(doc => {
// update doc
});
});
But querySnapshot.docs has 0 elements. I checked the same code in functions and it works properly. What could be the cause of this? If this is not possible are there any workarounds where I can bypass timeout using cloud functions?
Firebase is initialized correctly both in my machine and directory. I tried a clean initialized directory too. Same code when passed to an firebase function endpoint and ran once works perfectly fine.
If you run a script written with the Admin SDK locally on your computer you need to initialize the SDK with an exported service account key file as explained in the doc.
The doc details how to:
Generate a private key file in JSON format from the Firebase console
Set an environment variable to the file path of the JSON file that contains your service account key.
Then you can do as follows:
const admin = require('firebase-admin');
admin.initializeApp({
credential: applicationDefault()
});
const db = admin.firestore();
db.collection('users')
.get()
.then(querySnapshot => {
return Promise.all(querySnapshot.docs.map(doc => doc.ref.update( {...} ))):
})
.then(() => {...})
.catch(...)
Note that to update several docs within a loop via the asynchronous update() method you'll need to use Promise.all(), as shown above.
When I initialized like this everything seemed to work fine. The reason why applicationDefault doesn't work is I think because doc says it works in google environments.
const admin = require('firebase-admin');
var serviceAccount = require('path/to/key.json')
admin.initializeApp({
credential: admin.credential.cert(serviceAccount)
});

Is it possible to access firebase on both server side and client side in NodeJS?

I'm working an app that need to access the firebase database on both client-side (to catch "on" event to grab recently added data) and server-side (to add record to the database). I'm not sure that I did it correctly that use 2 db instances are required on both client and server OR create 1 on the server and use it on the client cause I got a warning on the local side saying that Firebase is already defined in the global scope.
This is how I declare the db instance on server-side, this works perfectly fine:
var admin = require("firebase-admin");
var serviceAccount = require("../config/sterminal-0000-firebase-adminsdk-bvuit-ce5ee771bc.json");
admin.initializeApp({
credential: admin.credential.cert(serviceAccount),
databaseURL: "https://sterminal-0000.firebaseio.com"
});
module.exports.admin = admin;
...
const {admin} = require('../extra/firebase');
let db = admin.database();
This is how I declare the db instance on client-side:
Include the libs to pug template
script(src="https://www.gstatic.com/firebasejs/7.14.2/firebase-app.js")
script(src="https://www.gstatic.com/firebasejs/7.14.2/firebase-database.js")
script(src="/javascripts/local.js" crossorigin="anonymous")
And in local script:
var firebaseConfig = {
apiKey: "AIzaSyCkip7lcHNNodJNhrO5n0Hog5Kvs100000",
authDomain: "sterminal-00000.firebaseapp.com",
databaseURL: "https://sterminal-00000.firebaseio.com",
projectId: "sterminal-8bf73",
storageBucket: "sterminal-00000.appspot.com",
messagingSenderId: "961511900000",
appId: "1:96151100000:web:f3cec40f38f7b7d4000000"
};
firebase.initializeApp(firebaseConfig);
firebase.database().ref("messages").on("child_added", function (snap) {
console.log(snap.val().message);
}); // ----> DOES NOT WORK
I got a warning on local-side:
logger.ts:115 [2020-04-27T18:43:48.559Z] #firebase/app:
Warning: Firebase is already defined in the global scope. Please make sure
Firebase library is only loaded once.
Yes, you can access Firebase Realtime Database from both client-side Node.js and server-side Node.js. But the SDK are separate, and you can't include both of them in a single project. The latter seems to be what is leading to the error you now have.

The default Firebase app already exists. This means you called initializeApp() more than once

I am just starting cloud functions with firebase. Here is my first function.
import * as functions from 'firebase-functions';
import express from 'express';
import admin from "firebase-admin"
admin.initializeApp(functions.config())
console.log('Firebase Environment setup success')
const app1 = express()
app1.get("*", (request, response) => {
response.send("bar")
})
const foo = functions.https.onRequest(app1)
module.exports = {
foo
}
Everytime I run this code with the emulator suite with
firebase emulators:start --only functions
And I visit the url output on the console, I get the error:
! Error: The default Firebase app already exists. This means you
called initializeApp() more than once without providing an app name as
the second argument. In most cases you only need to call
initializeApp() once. But if you do want to initialize multiple apps,
pass a second argument to initializeApp() to give each app a unique
name.
at FirebaseAppError.FirebaseError [as constructor] (C:\Users\Business\PhpstormProjects\gantt-flexx\node-server\node_modules\firebase-admin\lib\utils\error.js:42:28)
at FirebaseAppError.PrefixedFirebaseError [as constructor] (C:\Users\Business\PhpstormProjects\gantt-flexx\node-server\node_modules\firebase-admin\lib\utils\error.js:88:28)
at new FirebaseAppError (C:\Users\Business\PhpstormProjects\gantt-flexx\node-server\node_modules\firebase-admin\lib\utils\error.js:122:28)
at FirebaseNamespaceInternals.initializeApp (C:\Users\Business\PhpstormProjects\gantt-flexx\node-server\node_modules\firebase-admin\lib\firebase-namespace.js:68:23)
at FirebaseNamespace.initializeApp (C:\Users\Business\PhpstormProjects\gantt-flexx\node-server\node_modules\firebase-admin\lib\firebase-namespace.js:392:30)
at Proxy. (C:\Users\Business\AppData\Roaming\npm\node_modules\firebase-tools\lib\emulator\functionsEmulatorRuntime.js:338:51)
at C:\Users\Business\AppData\Roaming\npm\node_modules\firebase-tools\lib\emulator\functionsEmulatorRuntime.js:641:30
at Generator.next ()
at fulfilled (C:\Users\Business\AppData\Roaming\npm\node_modules\firebase-tools\lib\emulator\functionsEmulatorRuntime.js:4:58)
at process._tickCallback (internal/process/next_tick.js:68:7) ! Your function was killed because it raised an unhandled error.

Can't determine Firebase Database URL when trying to read Firebase Database from within Node.js Firebase function

I am using Flutter to build an app that accesses the Firebase database. All good from the Flutter side....but I am new to Node.js and Cloud Functions. I am trying to create a Node.js function to react to a deletion event of a record on one Firebase Database node and then delete records from two other Firebase Database nodes and image files from Firestore.
I am reacting to the trigger event with a functions.database.onDelete call, no problem, but falling at the very next hurdle i.e.trying to read admin.database to get a snapshot.
I have created a dummy function that uses .onUpdate to pick up a trigger event (don't want to keep having to recreate my data as I would if I used .onDelete) and then tries to read my Firebase Database to access a different node. The trigger event is picked up fine but I don't seem to have a database reference Url to do the read...yet it is the same database. Output on the console log from a call to process.env.FIREBASE_CONFIG shows the Url is present.
The included function code also has commenting to show the various outputs I get on the console log.
I am going crazy over this.....PLEASE can anyone tell me where I am going wrong. Been searching Google, Stackoverflow, Firebase docs for the last two days :-(
const admin = require("firebase-admin"); // Import Admin SDK
const functions = require("firebase-functions"); // Import Cloud Functions
admin.initializeApp({
credential: admin.credential.cert(
require("./user-guy-firebase-adminsdk.json")
)
});
exports.testDeleteFunction = functions.database
.ref("/user-guys/{userGuyId}")
// Using .onUpdate as I don't want to keep restoring my data if I use .onDelete
.onUpdate((snapshot, context) => {
const userData = snapshot.after.val();
const userId = userData.userId;
console.log('userId: ' + userId); // Gives correct console log output: userId: wajzviEcUvPZEcMUbbkPzcw64MB2
console.log(process.env.FIREBASE_CONFIG);
// Gives correct console log output:
// {"projectId":"user-guy","databaseURL":"https://user-guy.firebaseio.com","storageBucket":"user-guy.appspot.com","cloudResourceLocation":"us-central"}
// I have tried each of the four following calls and received the console log message as indicated after each.
//
// var root = admin.database.ref(); // Console Log Message: TypeError: admin.database.ref is not a function
// var root = admin.database().ref(); // Console Log Message: Error: Can't determine Firebase Database URL.
// var root = admin.database.ref; // Fails at line 31 below with the message indicated.
// var root = admin.database().ref; // Console Log Message: Error: Can't determine Firebase Database URL.
console.log(root.toString); // Console Log Message: TypeError: Cannot read property 'toString' of undefined.
// This is intended to read a chat thread for two users but processing never gets here.
var database = root.child('chats').child('0cSLt3Sa0FS26QIvOLbin6MFsL43GUPYmmAg9UUlRLnW97jpMCAkEHE3');
database
.once("value")
.then(snapshot => {
console.log(snapshot.val());
}, function (errorObject) {
console.log("The read failed: " + errorObject.code);
});
return null; // Will do stuff here once working.
});
Error messages shown in code comments.
If you want to use the configuration in FIREBASE_CONFIG, you should initialize the Admin SDK with no parameters:
admin.initializeApp();
This will use the default service account for your project, which should have full read and write access to the database.
You need to add your database url in admin.initializeApp
admin.initializeApp({
databaseURL:"your_database_url"
});
select Realtime Database in firebase and copy your url add in settings in fire config or watch this video https://www.youtube.com/watch?v=oOm_9y3vb80
config example
const config = {
apiKey: "",
authDomain: "",
projectId: "",
databaseURL: "https://youUrl.firebaseio.com/",
storageBucket: "",
messagingSenderId: "",
appId: "",
measurementId: ""
};
See:
https://firebase.google.com/docs/admin/setup#initialize_without_parameters
https://firebase.google.com/docs/functions/database-events
Try initialize without parameters.
The SDK can also be initialized with no parameters. In this case, the SDK uses Google Application Default Credentials and reads options from the FIREBASE_CONFIG environment variable. If the content of the FIREBASE_CONFIG variable begins with a { it will be parsed as a JSON object. Otherwise the SDK assumes that the string is the name of a JSON file containing the options.
const admin = require("firebase-admin"); // Import Admin SDK
const functions = require("firebase-functions"); // Import Cloud Functions
admin.initializeApp();
Same issue 3 years later...
After DAYS! I found out all of the Flutter documents have code for Firestore instead of Firebase.
Basically there are two products. Firestore Database, and Real-time Database. You are calling the Real-time Database methods, but probably have a Firestore database.
Try admin.firebase().ref('/some_collection').push();
Basically everywhere you're calling .database(), replace it with .firebase() if you are using Firebase. Yes, the Flutter tutorials are mis-leading!!!

Error: The default Firebase app does not exist

I'm tryin to do a simple function about Reading Data Once. but I get error like this:
index.js
var firebase = require("firebase");
var config = {
apiKey: "some api key",
authDomain: "fitto-exercise.firebaseapp.com",
databaseURL: "https://fitto-exercise.firebaseio.com",
projectId: "fitto-exercise",
storageBucket: "fitto-exercise.appspot.com",
messagingSenderId: "some number"
};
firebase.initializeApp(config);
and the search.js is here:
var firebase = require('.');
var admin = require("firebase-admin");
var db = admin.database();
var ref = db.ref("exercises/exercise");
ref.once("58.967", function(data) {
console.log("Got it!");
});
index.js and search.js in the same directory
I'm still inexperienced about this stuff maybe there are some noob mistakes.
This is my database looks like:
A couple problems here. If you're trying to require() some other file, it needs to have an export defined. In index.js (if that's what you're trying to require), doesn't have an export.
I'd suggest using just a single file for now, until you get your most basic code to work.
Also, according to the API documentation for once(), the method accepts, as its first argument:
One of the following strings: "value", "child_added", "child_changed",
"child_removed", or "child_moved."
"58.967" isn't one of them, and I don't know what you were intending to do there. But you probably want to use "value" to get the value of a child in the database.

Resources