Permanently change cloud function region - firebase

I know you can change the region of a function using the below method. Just wondering if there is a way to permanently set this to all functions so I dont have to do this to each function.
exports.myStorageFunction = functions
.region('europe-west1')
.storage
.object()
.onFinalize((object) => {
// ...
}); ```

Because of the chaining builder pattern, you can do this:
const euFunctions = functions.region('europe-west1');
exports.myFunction = euFunctions.storage.object().onFinalize(...);
and it will do what you expect!

One could improve it a little bit by defining an array and use that for all functions. But otherwise than that, there is no other way to my knowledge.
const regionArr = ["europe-west3"];
exports.myFunction = functions.region(...regionArr).https.onCall(async (data, context) => {
...
});

Related

Vue 3: StopHandle for computed()?

In Vue 3, watchEffect() and watch() returns StopHandle which allows the caller to stop watching.
I think that computed() should have a kind of StopHandle since computed() uses (it's my guess) a kind of 'watch' internally to track dirtiness, but there is none.
Is there a reason that computed() has no StopHandle-like thing? Or is there a function that works similarly to StopHandle?
Thanks.
You can use effectScope to manually dispose effects like computed or watch like this:
const scope = effectScope()
scope.run(() => {
const doubled = computed(() => counter.value * 2)
watch(doubled, () => console.log(doubled.value))
watchEffect(() => console.log('Count: ', doubled.value))
})
// to dispose all effects in the scope
scope.stop()
An unofficial way is calling the stop function directly from the computed variable:
const doubled = computed(() => counter.value * 2)
doubled.effect.stop()

Combine two arrays on Firebase Cloud Function

I have these two nodes that I need to get on a single http call. I am trying to achieve this by using async/await to get the two nodes and then combine them using concat or forEach. But it seems that even though I am awaiting responses, inside the function they are still promises and not the data itself. This is my basic example:
exports.searchVisit = functions.https.onRequest(async (req, res) => {
const today = new Date(Date.now());
let todayVisits = await admin.database().ref('/visits/').once('value');
let frequentVisits = await admin.database().ref('/frequent_visits/').once('value');
console.log(todayVisits); // Prints an object (I guess it is a promise)
res.status(200).send(todayVisits); // Returns correctly the data on visits collection
});
How could I achieve to return todayVisits and frequentVisits combined? Thanks in advance.
In your code, todayVisits is a DataSnapshot type object. It is not a promise. Logging that DataSnapshot object is not likely to be useful. If you want to see the raw data inside that snapshot, call val() on it to get a JavaScript object with the entire set of data in that snapshot. This is also what you probably want to send to the client (not the entire contents of the DataSnapshot).
The following code, merging the two JavaScript objects obtained with val(), as explained by Doug, should do the trick:
exports.searchVisit = functions.https.onRequest(async (req, res) => {
const today = new Date(Date.now());
let todayVisits = admin.database().ref('/visits/').once('value');
let frequentVisits = admin.database().ref('/frequent_visits/').once('value');
const [todayVisitsSnap, frequentVisitsSnap] = await Promise.all([
todayVisits,
frequentVisits
]);
res.status(200).send({ ...todayVisitsSnap.val(), ...frequentVisitsSnap.val() });
});

I can't seem replicate my data in firestore to algolia

Basically, I'm trying to replicate my data that's already in firebase into algolia through firebase cloud functions. The code doesn't compile and I can't seem to figure out why.
I'm using typescript, not javascript and am following this article right here.
https://medium.com/#soares.rfarias/how-to-set-up-firestore-and-algolia-319fcf2c0d37
I'm also working in VScode
// This is at the top of my file
const algoliasearch = require('algoliasearch')
const algoliaClient =
algoliasearch(functions.config().algolia.appid,
functions.config().algolia.apikey)
export const sendCollectionToAlgolia =
functions.https.onRequest(async (req, res) =>
{
const collectionIndex = algoliaClient.initIndex('Organizations')
const db = admin.firestore()
const algoliaRecords = []
const querySnapshot = await db.collection("Organizations").get()
querySnapshot.docs.forEach(doc => {
const document = doc.data()
const record = {
objectID: doc.id,
"orgUsername": document.orgUsername,
"orgName": document.orgName,
"school": document.school
}
algoliaRecords.push(record)
})
collectionIndex.saveObjects(algoliaRecords, (_error: any, content:
any) => {
res.status(200).send("COLLECTION was indexed to Algolia
successfully.");
})
})
I keep getting the compile error that says "Variable 'algoliaRecords' implicitly has type 'any[]' in some locations where its type cannot be determined" and I do not know how to fix it. I'm relatively new to algolia but have been doing cloud functions for a little bit.
This happens because algoriaRecords does not have an explicit type. Typically, TypeScript will infer types based on what you end up assigning later on. However, each subsequent algoriaRecords.push() operation evolves the type of the variable in accordance with the elements added to it.
A quick fix to this is by explicitly giving a type to algoriaRecords like such:
const algoriaRecords:Object[] = []
Furthermore, you can make TypeScript tolerate params with no types declared, see here for more information by configuring your tsconfig.js file and settting the noImplicitAny to false while removing the strict rule
// "strict": true
"noImplicitAny" : false

How can retrieve {pushId} with firebase cloud functions?

I am learning firebase cloud functions. I have a function that looks like that:
exports.gameLoopBeing = functions.database.ref('/tables/{pushId}/gamestarted')
.onWrite(event => {
//I want to retrieve the pushID
console.log(event.data.pushID);
});
event.data.pushID clearly doesn't work. How can retrieve the pushID? I looked at the docs and couldn't find anything.
For those who don't know that pushId is. This function listens to every change done inside elements inside /table. For example:
in /table/1 the pushId is 1
in /table/2 the pushId is 2
in /table/N the pushID is N
The wildcards in the ref path are provided in the event params object:
exports.gameLoopBeing = functions.database.ref('/tables/{pushId}/gamestarted')
.onWrite(event => {
//I want to retrieve the pushID
console.log(event.params.pushId);
});
exports.gameLoopBeing = functions.database.ref('/tables/{pushId}/gamestarted')
.onWrite((change, context) => {
//I want to retrieve the pushID
console.log(context.params.pushId);
});

Data validation using RxJS

I have the following function that validates that rangeFrom is not superior to rangeTo and that the rangeFrom does not already exist in the list of ranges.
How can rewrite this using RxJS?
const isTagAlreadyExist = (tags, currentTag) => _(tags)
.filter(x => x.id !== currentTag.id)
.some(x => _.inRange(currentTag.rangeTo, x.rangeFrom, x.rangeTo))
.value();
const validateRangeFrom = (tags, currentTag) => {
const errors = {};
if (isNumeric(currentTag.rangeFrom)) {
if (!_.inRange(currentTag.rangeFrom, 0, currentTag.rangeTo)) {
errors.rangeFrom = 'FROM_TAG_CANNOT_BE_GREATER_THAN_TO_TAG';
} else if (isTagAlreadyExist(tags, currentTag)) {
errors.rangeFrom ='TAG_ALREADY_EXISTS';
}
}
return {
errors
};
};
The question is: what parts do you want to rewrite to rxjs? Those are two pure functions that run synchronously from what I can see, I do not really see much a usecase for rxjs here - of course you could always utilize your functions within an rxjs stream:
const validateRangeFrom$ = (tags, currentTag) => {
return Observable.of(currentTag)
.map(tag => validateRangeFrom(tags, tag));
}
validateRangeFrom$(myTags, currentTag)
.subscribe(errors => console.log(errors));
But as you can see, this does not make much sense if you simply wrap it inside a stream, the essence of useful reactive programming is, that everything is reactive, not just some small parts, so for your example, you should start with having tags$ and currentTag$ as observables - let's assume that you have that, then you could do something like:
const tags$: Observable<ITag[]>... // is set somewhere, and emits a new array whenever it is changed
const currentTag$: Observable<ITag>... // is set somewhere and emits the tag whenever a new currentTag is set
const validateRangeFrom$ = Observable
.combineLatest(tags$, currentTag$, (tags, tag) => ({tags, tag}))
.map(({tags, tag}) => validateRangeFrom(tags, tag));
validateRangeFrom$.subscribe(errors => console.log(errors));
This will automatically trigger the validation for you whenever a new tags-array is emitted or a new currentTag is selected/set - but again: your validation-method is kept the same - as even in reactive programming you have to do validation and logic-operations at some point, the reactive part usually just concerns the flow of the data (see: tags$ and currentTag$)

Resources