Reputation: 265
I've been through the different topics related to my issue but couldn't fix it. My firebase cloud function with the onCreate trigger does not deploy. I get this error : Failed to load function definition from source: Failed to generate manifest from function source: SyntaxError: await is only valid in async functions and the top level bodies of modules
// add action to users when they have the objective already added
exports.addActionToUserWhenCreated = functions.firestore
.document('actions/{documentUid}')
.onCreate(async (snap, context) => {
// get the objectives
let actionObjectives = snap.data().objectives
let actionId = snap.id
let objSelectedBy = []
// For each objective, get the selectedBy field
actionObjectives.forEach(objective => {
const docSnap = await db.doc(`objectives/${objective}`).get()
objSelectedBy = docSnap.data().selectedBy
objSelectedBy.forEach(user => {
// Add the actionId to the user's selectedActions
db.doc(`users/${user}/selectedActions/${actionId}`).set({
achievedRate: 0,
})
})
// Add all the userIds to the action's selectedBy field
db.doc(`actions/${actionId}`).update({
selectedBy: objSelectedBy,
}, {merge: true});
})
return;
});
Do you see the problem? Thanks! Max
Upvotes: 2
Views: 1298
Reputation: 265
Got this sorted out but it took me some time and precious help from Puff!
First issue here : the forEach => await cannot be used in the forEach but it works with a for...of loop.
Second : Promise.all after the await => Original answer from Puff here.
The working case of this function is therefore :
To make it understandable, you can replace action with product and objective with category. It would be as if you want to automatically add a newly created product to every users that are following a specific category.
exports.addActionToUserWhenCreated = functions.firestore
.document('actions/{documentUid}')
.onCreate(async (snap, context) => {
// get the objectives
let actionObjectives = snap.data().objectives
let actionId = snap.id
let actionSelectedBy = []
// For each objective,
for (const objective of actionObjectives) {
// get the selectedBy field (array of userIds)
const snap = await db.doc(`objectives/${objective}`).get()
const objSelectedBy = snap.data().selectedBy;
console.log("objSelectedBy",objSelectedBy)
// Add the actionId to the user's selectedActions
Promise.all(objSelectedBy.map(user => {
return db.doc(`users/${user}/selectedActions/${actionId}`).set({
achievedRate: 0,
})
}))
// Add all the objectives' userIds to the action's selectedBy field (removing duplicate):
actionSelectedBy = [...new Set([...actionSelectedBy ,...objSelectedBy])]
}
// Update the action's selectedBy field :
db.doc(`actions/${actionId}`).update({
selectedBy: actionSelectedBy,
}, {merge: true});
});
Upvotes: 2