1

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

Maxime Crtgn
  • 175
  • 2
  • 10

1 Answers1

1

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});
});
marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
Maxime Crtgn
  • 175
  • 2
  • 10