How can I parameterize a Firebase API call within a closure? - javascript

I'm using Firebase cloud functions to sync my Firestore db to a 3rd party db. Since my cloud functions use calls to a 3rd party API, I want to parameterize the api call as an input to use dependency injection while testing. The only way I can think of doing this is basically putting the cloud function within a regular function, i.e.,:
function foo(apiCall = api) {
exports.bar =
functions.firestore.document(doc_name).onCreate(snapshot => apiCall(snapshot));
return exports.bar
}
foo();
When I try to deploy with firebase deploy --only functions I'm told firebase doesn't see the functions as existing in the local source code.
I've additionally tried something like to no effect:
function foo(apiCall = api) {
return functions.firestore.document(doc_name).onCreate(snapshot => apiCall(snapshot));
}
exports.bar = foo();
When I put exports.bar outside of the function, it deploys fine.
This is my first time using Firebase so I'm not too familiar with the syntax and such, but I don't know why wrapping the cloud function with a regular function wouldn't work - any suggestions?

What you're trying to do isn't possible. The exports must be defined statically at the top level of index.js so that the CLI can find and deploy them. They can't be exported dynamically through a function.

Related

Deploy firebase storage triggerd function on different environments

I'm having trouble to deploy my firebase function on my production environment since the buckets between dev and prod have different names. They are not the default buckets.
exports.myFunction= functions
.region("europe-west1")
.storage
.bucket("myDevBucket")
.object()
.onFinalize(
async (object) => {
[My code]
});
I struggle finding a way to use a variable instead of "myDevBucket" to be able to deploy using my CD on the production.
If you have any tips on that, I'll be glad to hear about them...
Thanks
Tried to use an .env variable which is not used during function deployment, so the default bucket was automatically selected.
Tried to use the defineString params firebase function, but the storage.bucket() does not handle these params (only the runWith() if I have understood correctly).

cloud function testing failing "Invalid request, unable to process."

I have written a simple cloud function which I also deployed already to firebase and the code works. It is the following function:
exports.testfunction = functions.https.onCall(async (data) => {
const mydata = JSON.parse(data)
const mydata1 = JSON.parse({const1: "AAA", const2: "BBB", const3: "CCC"})
return{mydata1}
});
Now that I want to test this function localy, Im running the following command in my terminal: firebase emulators:start and I get no errors so far. Anyways as soon as I try to call the function with http://localhost:5001/MYPROJECTNAME/us-central1/testfunction in my browser, Im receiving the following error message which I can not find any workaround for:
{"error":{"message":"Bad Request","status":"INVALID_ARGUMENT"}}
The thing is, the function itself is working great if I deploy it and call it from inside my app, but Im failing to run it from my firebase emulator inside the console.
What am I doing wrong here?
As explained in the documentation for Callable Cloud Functions:
It's important to keep in mind that HTTPS callable functions are
similar but not identical to HTTP functions. To use HTTPS callable
functions you must use the client SDK for your platform together with
the functions.https backend API (or implement the protocol).
So, if you want to directly call the function via it's URL, your HTTP Request needs to follow the protocol specification for https.onCall.

AWS SAM: How to locally invoke all Node.js functions instead one by one?

I am developing a REST API with AWS Lambda, API Gateway, RDS (MySQL). I am using Node.js. I am also using AWS SAM tool.
In my API I have lambda functions that accept URL parameters and that do not accept them.
I noticed that I can deploy these to AWS without an issue, and then execute from POSTMAN.
However when I try to locally run them, I am running into problems.
When I execute sam local invoke, it says Error: You must provide a function logical ID when there are more than one functions in your template. So I had to execute them one by one, like sam local invoke FunctionName
When I try to invoke a function that accepts URL parameters, it says TypeError: Cannot destructure property 'id' of 'event.queryStringParameters' as it is undefined. Here the id is the name of the URL Param.
So,
How can I locally invoke all node.js functions, instead of one by one?
How can I make sure that functions with URL Params also can be locally invoked?
In Node.JS, it is not possible to locally invoke all at once. sam local invoke FUNCTION_NAME is the way to go.
Since the question is about a REST API, if you want to check how thE rest api is working, all you have to do is this
sam build
sam local start-api
I normally run the following without build since it helps to view the changes during development:
sam local start-api 2>&1 | tr “\r” “\n”

Can't change data in Firebase Realtime Database when using Cloud Functions

I want to reset a specific value in my Firebase Realtime Database every day at 12:00 AM. I'm using Firebase Cloud Functions to do this. This is the code that I have:
exports.dailyReset = functions.pubsub.schedule('0 0 * * *').onRun((context) => {
exports.resetValue = functions.database.ref('/users/{userId}')
.onWrite((change, context) => {
var ref = change.data.ref;
ref.update({
"daily": 0
});
return ref.update({"daily": 0});
});
return null;
});
Upon testing the script, it doesn't work. It's not resetting the value in my Firebase Realtime Database. Can someone tell me how do I fix this?
It's not possible to use the Functions SDK to write to the database. functions can only be used to establish triggers that run when the triggering event occurs.
In other words, functions.database.ref('/users/{userId}').onWrite() isn't going to write anything at all.
If you want to write to Realtime Database from a nodejs program, you should use the Firebase Admin SDK to write data.
The Cloud Functions triggers in your index.js file have to be known and fixed when run firebase deploy. That means you can't dynamically create triggers from inside a Cloud Functions, as you're trying to do.
The common approaches for dynamic scheduling are:
Have a single Cloud Function that runs periodically and then executes the tasks for the past time period.
Dynamically schedule Cloud Functions with Cloud Tasks, as Doug describes in his blog post How to schedule a Cloud Function to run in the future with Cloud Tasks (to build a Firestore document TTL).
But in your case, why do you even need the onWrite trigger? Can't you just import the Admin SDK, user that to read all users, and then delete them?

Cloud Functions - How to instantiate global functions/variables only once?

I have a firebase application that uses Cloud Functions to talk to a Google Cloud SQL instance. These cloud functions are used to perform CRUD actions. I would like to ensure that the database reflects the CRUD operations, as such, run migration code every time I push new function code to ensure the database is always up to date.
I do this in a global function
const functions = require('firebase-functions')
const pg = require('pg')
// Create if not exists database
(function() {
console.log('create db...')
})()
exports.helloWorld = functions.https.onRequest((request, response) => {
console.log('Hello from Firebase function log!')
response.send('Hello from Firebase!')
})
exports.helloWorld2 = functions.https.onRequest((request, response) => {
console.log('Hello from Firebase function log 2!')
response.send('Hello from Firebase 2!')
})
This console log then runs twice when I deploy.
Now I understand that there is no way of knowing how many instances Cloud Functions will spin up for the functions, as stated in their docs:
The global scope in the function file, which is expected to contain the function definition, is executed on every cold start, but not if the instance has already been initialized.`
If I add a third function, this console log is now shown 3 times in the logs, instead of 2, one for each function. Would it be correct in saying that there's a new instance for every single function uploaded? I am trying to understand what happens under the hood when I upload a set of cloud functions.
If so - is there no reliable way to run migration code inside a global function in cloud functions?
What you're doing isn't a supported use case for Cloud Functions. Cloud Functions code runs in response to events that occur in your project. There is no "one time" function invocations that happen on deployment. If you need to run code a single time, just run that from your desktop or some other server you control.
You should also strive to minimize the amount of work that happens in the global scope of your functions. Globals will be instantiated and run once for each allocated server instance running a function in your app, as each function runs in full isolation of each other, and each has its own copy of everything. Watch my video about function scaling and isolation to better understand this behavior.

Categories

Resources