9

Ok, y'all I am in a pickle here. I've been working on all my firebase functions for a few days and thought I was making really good progress until I went to deploy after several days of testing with the firebase server and postman... It won't deploy T_T

The error I am getting in the terminal when I use firebase --debug deploy is:

2022-01-25T17:23:50.575Z] Total Function Deployment time: 57866
[2022-01-25T17:23:50.575Z] 1 Functions Deployed
[2022-01-25T17:23:50.575Z] 1 Functions Errored
[2022-01-25T17:23:50.575Z] 0 Function Deployments Aborted
[2022-01-25T17:23:50.575Z] Average Function Deployment time: 57864

Functions deploy had errors with the following functions:
        api(us-central1)
[2022-01-25T17:23:50.713Z] Missing URI for HTTPS function in printTriggerUrls. This shouldn't happen
in  functions: cleaning up build files... 
[2022-01-25T17:23:50.719Z] >>> [apiv2][query] DELETE https://artifactregistry.googleapis.com/v1beta2/projects/lxai-mentor-matching/locations/us-central1/repositories/gcf-artifacts/packages/api [none]
[2022-01-25T17:23:50.722Z] >>> [apiv2][query] GET https://us.gcr.io/v2/lxai-mentor-matching/gcf/us-central1/tags/list [none]
[2022-01-25T17:23:50.918Z] <<< [apiv2][status] GET https://us.gcr.io/v2/lxai-mentor-matching/gcf/us-central1/tags/list 200
[2022-01-25T17:23:50.918Z] <<< [apiv2][body] GET https://us.gcr.io/v2/lxai-mentor-matching/gcf/us-central1/tags/list {"child":["5fbdb989-6e6d-42bc-9a25-3073c3098d76"],"manifest":{},"name":"lxai-mentor-matching/gcf/us-central1","tags":[]}
[2022-01-25T17:23:50.918Z] >>> [apiv2][query] GET https://us.gcr.io/v2/lxai-mentor-matching/gcf/us-central1/5fbdb989-6e6d-42bc-9a25-3073c3098d76/tags/list [none]
[2022-01-25T17:23:50.931Z] <<< [apiv2][status] DELETE https://artifactregistry.googleapis.com/v1beta2/projects/lxai-mentor-matching/locations/us-central1/repositories/gcf-artifacts/packages/api 404
[2022-01-25T17:23:50.933Z] <<< [apiv2][body] DELETE https://artifactregistry.googleapis.com/v1beta2/projects/lxai-mentor-matching/locations/us-central1/repositories/gcf-artifacts/packages/api {"error":{"code":404,"message":"Repository does not exist: \"projects/lxai-mentor-matching/locations/us-central1/repositories/gcf-artifacts\"","status":"NOT_FOUND"}}
[2022-01-25T17:23:51.061Z] <<< [apiv2][status] GET https://us.gcr.io/v2/lxai-mentor-matching/gcf/us-central1/5fbdb989-6e6d-42bc-9a25-3073c3098d76/tags/list 200
[2022-01-25T17:23:51.063Z] <<< [apiv2][body] GET https://us.gcr.io/v2/lxai-mentor-matching/gcf/us-central1/5fbdb989-6e6d-42bc-9a25-3073c3098d76/tags/list {"child":["cache"],"manifest":{"sha256:efea96d0dec08db58767f472cc16a3c17c277e41d844a61bbdb745e49c7cd8e6":{"imageSizeBytes":"421918451","layerId":"","mediaType":"application/vnd.docker.distribution.manifest.v2+json","tag":["api_version-15","latest"],"timeCreatedMs":"315532801000","timeUploadedMs":"1643131418106"}},"name":"lxai-mentor-matching/gcf/us-central1/5fbdb989-6e6d-42bc-9a25-3073c3098d76","tags":["api_version-15","latest"]}
[2022-01-25T17:23:51.064Z] >>> [apiv2][query] GET https://us.gcr.io/v2/lxai-mentor-matching/gcf/us-central1/5fbdb989-6e6d-42bc-9a25-3073c3098d76/cache/tags/list [none]
[2022-01-25T17:23:51.069Z] >>> [apiv2][query] DELETE https://us.gcr.io/v2/lxai-mentor-matching/gcf/us-central1/5fbdb989-6e6d-42bc-9a25-3073c3098d76/manifests/api_version-15 [none]
[2022-01-25T17:23:51.230Z] <<< [apiv2][status] DELETE https://us.gcr.io/v2/lxai-mentor-matching/gcf/us-central1/5fbdb989-6e6d-42bc-9a25-3073c3098d76/manifests/latest 202
[2022-01-25T17:23:51.231Z] <<< [apiv2][body] DELETE https://us.gcr.io/v2/lxai-mentor-matching/gcf/us-central1/5fbdb989-6e6d-42bc-9a25-3073c3098d76/manifests/latest {"errors":[]}
[2022-01-25T17:23:51.250Z] <<< [apiv2][status] GET https://us.gcr.io/v2/lxai-mentor-matching/gcf/us-central1/5fbdb989-6e6d-42bc-9a25-3073c3098d76/cache/tags/list 200
[2022-01-25T17:23:51.250Z] <<< [apiv2][body] GET https://us.gcr.io/v2/lxai-mentor-matching/gcf/us-central1/5fbdb989-6e6d-42bc-9a25-3073c3098d76/cache/tags/list {"child":[],"manifest":{"sha256:75f8940b6524c90f2b653b387e0cab4a9ae9f3dbebb2e5f4dfb03fc3345ead6f":{"imageSizeBytes":"13412478","layerId":"","mediaType":"application/vnd.docker.distribution.manifest.v2+json","tag":["latest"],"timeCreatedMs":"315532801000","timeUploadedMs":"1643131418618"}},"name":"lxai-mentor-matching/gcf/us-central1/5fbdb989-6e6d-42bc-9a25-3073c3098d76/cache","tags":["latest"]}
[2022-01-25T17:23:51.251Z] >>> [apiv2][query] DELETE https://us.gcr.io/v2/lxai-mentor-matching/gcf/us-central1/5fbdb989-6e6d-42bc-9a25-3073c3098d76/cache/manifests/latest [none]
[2022-01-25T17:23:51.256Z] <<< [apiv2][status] DELETE https://us.gcr.io/v2/lxai-mentor-matching/gcf/us-central1/5fbdb989-6e6d-42bc-9a25-3073c3098d76/manifests/api_version-15 202
[2022-01-25T17:23:51.256Z] <<< [apiv2][body] DELETE https://us.gcr.io/v2/lxai-mentor-matching/gcf/us-central1/5fbdb989-6e6d-42bc-9a25-3073c3098d76/manifests/api_version-15 {"errors":[]}
[2022-01-25T17:23:51.257Z] >>> [apiv2][query] DELETE https://us.gcr.io/v2/lxai-mentor-matching/gcf/us-central1/5fbdb989-6e6d-42bc-9a25-3073c3098d76/manifests/sha256:efea96d0dec08db58767f472cc16a3c17c277e41d844a61bbdb745e49c7cd8e6 [none]
[2022-01-25T17:23:51.386Z] <<< [apiv2][status] DELETE https://us.gcr.io/v2/lxai-mentor-matching/gcf/us-central1/5fbdb989-6e6d-42bc-9a25-3073c3098d76/cache/manifests/latest 202
[2022-01-25T17:23:51.386Z] <<< [apiv2][body] DELETE https://us.gcr.io/v2/lxai-mentor-matching/gcf/us-central1/5fbdb989-6e6d-42bc-9a25-3073c3098d76/cache/manifests/latest {"errors":[]}
[2022-01-25T17:23:51.387Z] >>> [apiv2][query] DELETE https://us.gcr.io/v2/lxai-mentor-matching/gcf/us-central1/5fbdb989-6e6d-42bc-9a25-3073c3098d76/cache/manifests/sha256:75f8940b6524c90f2b653b387e0cab4a9ae9f3dbebb2e5f4dfb03fc3345ead6f [none]
[2022-01-25T17:23:51.683Z] <<< [apiv2][status] DELETE https://us.gcr.io/v2/lxai-mentor-matching/gcf/us-central1/5fbdb989-6e6d-42bc-9a25-3073c3098d76/manifests/sha256:efea96d0dec08db58767f472cc16a3c17c277e41d844a61bbdb745e49c7cd8e6 202
[2022-01-25T17:23:51.683Z] <<< [apiv2][body] DELETE https://us.gcr.io/v2/lxai-mentor-matching/gcf/us-central1/5fbdb989-6e6d-42bc-9a25-3073c3098d76/manifests/sha256:efea96d0dec08db58767f472cc16a3c17c277e41d844a61bbdb745e49c7cd8e6 {"errors":[]}
[2022-01-25T17:23:51.728Z] <<< [apiv2][status] DELETE https://us.gcr.io/v2/lxai-mentor-matching/gcf/us-central1/5fbdb989-6e6d-42bc-9a25-3073c3098d76/cache/manifests/sha256:75f8940b6524c90f2b653b387e0cab4a9ae9f3dbebb2e5f4dfb03fc3345ead6f 202
[2022-01-25T17:23:51.729Z] <<< [apiv2][body] DELETE https://us.gcr.io/v2/lxai-mentor-matching/gcf/us-central1/5fbdb989-6e6d-42bc-9a25-3073c3098d76/cache/manifests/sha256:75f8940b6524c90f2b653b387e0cab4a9ae9f3dbebb2e5f4dfb03fc3345ead6f {"errors":[]}
[2022-01-25T17:23:51.852Z] Error: Failed to update function api in region us-central1
    at /Users/tmac/.nvm/versions/node/v17.3.0/lib/node_modules/firebase-tools/lib/deploy/functions/release/fabricator.js:38:11
    at processTicksAndRejections (node:internal/process/task_queues:96:5)
    at async Fabricator.updateV1Function (/Users/tmac/.nvm/versions/node/v17.3.0/lib/node_modules/firebase-tools/lib/deploy/functions/release/fabricator.js:255:32)
    at async Fabricator.updateEndpoint (/Users/tmac/.nvm/versions/node/v17.3.0/lib/node_modules/firebase-tools/lib/deploy/functions/release/fabricator.js:136:13)
    at async handle (/Users/tmac/.nvm/versions/node/v17.3.0/lib/node_modules/firebase-tools/lib/deploy/functions/release/fabricator.js:75:17)

Error: There was an error deploying functions

Having read a few other posts here I am super confused as to what the error is and where I can hunt it down. Everything has been working locally with firebase serve. When I check the log files I get this:


11:23:52.550 AM
api
{"@type":"type.googleapis.com/google.cloud.audit.AuditLog","status":
{"code":3,"message":"Function failed on loading user code. This is likely due to a bug in the user code. Error message: Error: please examine your function logs to see the error cause: https://cloud.google.com/functions/docs/monitoring/logging#viewing_logs. Additional troubleshooting documentation can be found at https://cloud.google.com/functions/docs/troubleshooting#logging. Please visit https://cloud.google.com/functions/docs/troubleshooting for in-depth troubleshooting documentation."},"authenticationInfo":{"principalEmail":"[email protected]"},"serviceName":"cloudfunctions.googleapis.com","methodName":"google.cloud.functions.v1.CloudFunctionsService.UpdateFunction","resourceName":"projects/lxai-mentor-matching/locations/us-central1/functions/api"}

One post here was about space in a file name, but that's not my issue, another was about package.json so I'm posting mine here but not sure what I am looking for. Any idea on how to dig deeper or what to look for so I can get deploy working again?

package.json

{
  "name": "functions",
  "description": "Cloud Functions for Firebase",
  "scripts": {
    "serve": "firebase emulators:start --only functions",
    "shell": "firebase functions:shell",
    "start": "npm run shell",
    "deploy": "firebase deploy --only functions",
    "logs": "firebase functions:log"
  },
  "engines": {
    "node": "16"
  },
  "main": "index.js",
  "dependencies": {
    "firebase-admin": "^9.8.0",
    "firebase-functions": "^3.14.1"
  },
  "devDependencies": {
    "firebase-functions-test": "^0.2.0"
  },
  "private": true
}

index.js

const functions = require('firebase-functions');
const app = require('express')();

const { postOneScream } = require('./handlers/screams');
const {
  signup,
  login,
  uploadImage,
  addUserDetails,
} = require('./handlers/users');
const { addMentee, getMentees, updateMentee } = require('./handlers/mentees');
const { addMentor, getMentors, updateMentor } = require('./handlers/mentors');

const { FBAuth } = require('./util/fbAuth');

//**POST ROUTES**
// Scream routes - Testing post functionality for social media feed posts
app.post('/screams', FBAuth, postOneScream);

// Signup route
app.post('/signup', signup);

// Sign In route
app.post('/login', login);

// Upload an image route
app.post('/users/image', FBAuth, uploadImage);

// Add details to user profile
app.post('/users', FBAuth, addUserDetails);

// Mentee Signup / Update
app.post('/mentees', FBAuth, addMentee);
app.post('/mentees', FBAuth, updateMentee);
// Mentor Signup
app.post('/mentors', FBAuth, addMentor);
app.post('/mentors', FBAuth, updateMentor);

//**GET ROUTES**

// Get all mentees
app.get('/mentees', getMentees);
// Get all mentors
app.get('/mentors', getMentors);

//**Export API**
// export api allows us to use express for our function formating
exports.api = functions.https.onRequest(app);

users.js

const { admin, db } = require('../util/admin');
const firebase = require('firebase');

const config = require('../util/config');
firebase.initializeApp(config);

const {
  validateSignupData,
  validateLoginData,
  reduceUserDetails,
} = require('../util/validators');

exports.signup = async (req, res) => {
  const newUser = {
    email: req.body.email,
    password: req.body.password,
    confirmPassword: req.body.confirmPassword,
    handle: req.body.handle,
  };

  // Validating the fields for user signup
  const { valid, errors } = validateSignupData(newUser);

  if (!valid) return res.status(400).json(errors);
  const noImg = 'no-img.png';

  const userDoc = await db.doc(`/users/${newUser.handle}`).get();
  if (userDoc.exists) {
    return res.status(400).json({ handle: 'This handle already taken' });
  } else {
    // Create user
    let userId;
    await firebase
      .auth()
      .createUserWithEmailAndPassword(newUser.email, newUser.password)
      .then((data) => {
        userId = data.user.uid;
        return data.user.getIdToken();
      })
      .then((userToken) => {
        // Add User to Users Collection
        const uToken = userToken;
        const userCredentials = {
          handle: newUser.handle,
          email: newUser.email,
          createdAt: new Date().toISOString(),
          imgURL: `https://firebasetorage.googleapis.com/v0/b/${config.storageBucket}/o/${noImg}?alt=media`,
          userId,
        };
        db.doc(`/users/${newUser.handle}`).set(userCredentials);
        return userToken;
      })
      .then((userToken) => {
        return res
          .status(201)
          .json({ message: 'User created successfully', token: userToken });
      })
      .catch((err) => {
        console.error(err);
        if (err.code === 'auth/email-already-in-use') {
          return res.status(400).json({ email: 'Email is already in use' });
        } else {
          return res.status(500).json({ error: err.code });
        }
      });
  }
};

exports.login = (req, res) => {
  const user = {
    email: req.body.email,
    password: req.body.password,
  };

  // Validating the fields for user login
  const { valid, errors } = validateLoginData(user);

  if (!valid) return res.status(400).json(errors);

  // Log the user in and get a token
  firebase
    .auth()
    .signInWithEmailAndPassword(user.email, user.password)
    .then((data) => {
      return data.user.getIdToken();
    })
    .then((token) => {
      res.json({ token });
    })
    .catch((err) => {
      console.error(err);
      if (err.code === 'auth/wrong-password') {
        return res.status(403).json({ general: 'Wrong credentials' });
      } else {
        return res.status(500).json({ error: err.code });
      }
    });
};

// Upload an image for user profile page
exports.uploadImage = (req, res) => {
  const BusBoy = require('busboy');
  const path = require('path');
  const os = require('os');
  const fs = require('fs');

  const busboy = BusBoy({ headers: req.headers });

  let imageFileName;
  let imageToBeUploaded = {};

  busboy.on('file', (fieldname, file, filename, encoding, mimetype) => {
    if (
      mimetype !== 'image/jpeg' &&
      mimetype !== 'image/png' &&
      mimetype !== 'image/jpg'
    ) {
      return res
        .status(400)
        .json({ error: 'Wrong file type, please use JPG/JPEG/PNG' });
    }
    const fileName = filename.filename + '';
    const imageExtention = fileName.split('.')[fileName.split('.').length - 1];
    // Not sure why we need to change file name but this is the tutorial recommendation
    imageFileName = `${Math.round(
      Math.random() * 10000000000,
    )}.${imageExtention}`;
    console.log(imageFileName);
    const filePath = path.join(os.tmpdir(), imageFileName);
    imageToBeUploaded = { filePath, mimetype };
    file.pipe(fs.createWriteStream(filePath));
  });
  busboy.on('finish', () => {
    admin
      .storage()
      .bucket()
      .upload(imageToBeUploaded.filePath, {
        resumable: false,
        metadata: {
          metadata: {
            contentType: imageToBeUploaded.mimetype,
          },
        },
      })
      .then(() => {
        const imgURL = `https://firebasestorage.googleapis.com/v0/b/${config.storageBucket}/o/${imageFileName}?alt=media`;
        return db.doc(`/users/${req.user.handle}`).update({ imgURL });
      })
      .then(() => {
        return res.json({ message: 'Image uploaded successfully' });
      })
      .catch((err) => {
        console.error(err);
        return res.status(500).json({ error: err.code });
      });
  });
  busboy.end(req.rawBody);
};

// Add user details to user collection in db / user profile in react
exports.addUserDetails = (req, res) => {
  let userDetails = reduceUserDetails(req.body);

  db.doc(`/users/${req.user.handle}`)
    .update(userDetails)
    .then(() => {
      return res.status(200).json({ message: 'Details added successfully' });
    })
    .catch((err) => {
      console.error(err);
      return res.status(500).json({ error: err.code });
    });
};

screams.js

const { db } = require('../util/admin');

exports.postOneScream = (req, res) => {
  const newScream = {
    body: req.body.body,
    userHandle: req.user.handle,
    createdAt: new Date().toISOString(),
  };

  db.collection('screams')
    .add(newScream)
    .then((doc) => {
      res.json({ message: `document ${doc.id} created successfully` });
    })
    .catch((err) => {
      res.status(500).json({ error: 'something went wrong' });
      console.error(err);
    });
};

mentees.js

const { db } = require('../util/admin');


const { reduceMenteeDetails } = require('../util/validators');


// Add a mentee to the mentees collection
exports.addMentee = (req, res) => {
    
    let menteeDetails = reduceMenteeDetails(req);

    db.doc(`/mentees/${req.user.handle}`).set(menteeDetails)
    .then(() => {
        return res.status(200).json({ message: 'Details added successfully' });
    }).catch(err => {
        console.error(err);
        return res.status(500).json({ error: err.code });
    })
}

// Get all Mentees from the mentee collection
exports.getMentees = (req, res) => {
    db.collection('mentees').get()
    .then((data) => {
        let mentees = [];
        data.forEach((doc) => {
            mentees.push(doc.data())
        });
        return res.json(mentees);
    })
    .catch(err => {
        console.error(err);
        return res.status(500).json({ error: err.code })
    })
}

// Update an existing mentee
exports.updateMentee = (req, res) => {
    let menteeDetails = reduceMenteeDetails(req);

    db.doc(`/mentees/${req.user.handle}`).update(menteeDetails)
    .then(() => {
        return res.status(200).json({ message: 'Details added successfully' });
    }).catch(err => {
        console.error(err);
        return res.status(500).json({ error: err.code });
    })
}

mentors.js

const { db } = require('../util/admin');

const { reduceMentorDetails } = require('../util/validators');

// Add a mentor to the mentors collection
exports.addMentor = (req, res) => {
  let mentorDetails = reduceMentorDetails(req);

  db.doc(`/mentors/${req.user.handle}`)
    .set(mentorDetails)
    .then(() => {
      return res.status(200).json({ message: 'Details added successfully' });
    })
    .catch((err) => {
      console.error(err);
      return res.status(500).json({ error: err.code });
    });
};

// Get all mentors from the mentor collection
exports.getMentors = (req, res) => {
  db.collection('mentors')
    .get()
    .then((data) => {
      let mentors = [];
      data.forEach((doc) => {
        mentors.push(doc.data());
      });
      return res.json(mentors);
    })
    .catch((err) => {
      console.error(err);
      return res.status(500).json({ error: err.code });
    });
};

// Update an existing mentor
exports.updateMentor = (req, res) => {
  let mentorDetails = reduceMentorDetails(req);

  db.doc(`/mentors/${req.user.handle}`)
    .update(mentorDetails)
    .then(() => {
      return res.status(200).json({ message: 'Details added successfully' });
    })
    .catch((err) => {
      console.error(err);
      return res.status(500).json({ error: err.code });
    });
};

validators.js

// Helper functions for validation of signup form
// Check if a field is empty
const isEmpty = (string) => {
  if (string.trim() === '') return true;
  else return false;
};

// Check if an email is valid in format
const isEmail = (email) => {
  const regEx =
    /^(([^<>()[\]\.,;:\s@\"]+(\.[^<>()[\]\.,;:\s@\"]+)*)|(\".+\"))@(([^<>()[\]\.,;:\s@\"]+\.)+[^<>()[\]\.,;:\s@\"]{2,})$/i;
  if (email.match(regEx)) return true;
  else return false;
};

//Validate signup credential entered
exports.validateSignupData = (data) => {
  let errors = {};

  if (isEmpty(data.email)) {
    errors.email = 'Must not be empty';
  } else if (!isEmail(data.email)) {
    errors.email = 'Must be a valid email';
  }
  if (isEmpty(data.password)) errors.password = 'Must not be empty';
  if (data.password !== data.confirmPassword)
    errors.confirmPassword = 'Passwords do not match';
  if (isEmpty(data.handle)) errors.handle = 'Must not be empty';

  return {
    errors,
    valid: Object.keys(errors).length === 0 ? true : false,
  };
};

// Validate Login Credentials entered
exports.validateLoginData = (data) => {
  let errors = {};
  if (isEmpty(data.email)) errors.email = 'Must not be empty';
  if (isEmpty(data.password)) errors.password = 'Must not be empty';

  return {
    errors,
    valid: Object.keys(errors).length === 0 ? true : false,
  };
};

// User Details Updater - Checks for non-answers/blanks and return dict
exports.reduceUserDetails = (data) => {
  let userDetails = {};

  if (!isEmpty(data.fullName.trim())) userDetails.fullName = data.fullName;
  if (!isEmpty(data.jobTitle.trim())) userDetails.jobTitle = data.jobTitle;
  if (!isEmpty(data.affiliation.trim()))
    userDetails.affiliation = data.affiliation;
  if (!isEmpty(data.homeLocation.trim()))
    userDetails.homeLocation = data.homeLocation;
  if (!isEmpty(data.isLatinX.trim())) userDetails.isLatinX = data.isLatinX;
  if (!isEmpty(data.bio.trim())) userDetails.bio = data.bio;
  if (!isEmpty(data.website.trim())) {
    // If user doesn't include the http://
    if (data.website.trim().substring(0, 4) !== 'http') {
      userDetails.website = `http://${data.website.trim()}`;
    } else userDetails.website = data.website;
  }
  if (!isEmpty(data.publicProfile.trim()))
    userDetails.publicProfile = data.publicProfile;

  return userDetails;
};

// Mentee Details Updater - Checks for non-answers/blanks and return dict
exports.reduceMenteeDetails = (data) => {
  const answers = data.body;
  let menteeDetails = {};

  // Things we can pull from the data.user or just geneate
  menteeDetails.createdAt = new Date().toISOString();
  menteeDetails.userId = data.user.uid;
  menteeDetails.email = data.user.email;
  menteeDetails.handle = data.user.handle;

  //Things we can pull from the user's info in the user collection
  menteeDetails.fullName = answers.fullName;
  menteeDetails.isLatinX = answers.isLatinX;
  menteeDetails.currentLocation = answers.currentLocation;

  // Questions we need to ask in the mentee sign up flow
  if (!isEmpty(answers.gender.trim())) menteeDetails.gender = answers.gender;
  if (!isEmpty(answers.countryOrigin.trim()))
    menteeDetails.countryOrigin = answers.countryOrigin;
  if (!isEmpty(answers.affiliation.trim()))
    menteeDetails.affiliation = answers.affiliation;
  if (!isEmpty(answers.position.trim()))
    menteeDetails.position = answers.position;
  if (!isEmpty(answers.scholarOrWebsite.trim())) {
    // If user doesn't include the http://
    if (answers.scholarOrWebsite.trim().substring(0, 4) !== 'http') {
      menteeDetails.scholarOrWebsite = `http://${answers.scholarOrWebsite.trim()}`;
    } else menteeDetails.scholarOrWebsite = answers.scholarOrWebsite;
  }
  if (answers.languages.length > 0) menteeDetails.languages = answers.languages;
  if (!isEmpty(answers.timezone.trim()))
    menteeDetails.timezone = answers.timezone;
  if (answers.mentorshipArea.length > 0)
    menteeDetails.mentorshipArea = answers.mentorshipArea;
  if (!isEmpty(answers.motivationStatement.trim()))
    menteeDetails.motivationStatement = answers.motivationStatement;
  if (answers.prefferedOutcomes.length > 0)
    menteeDetails.prefferedOutcomes = answers.prefferedOutcomes;
  if (!isEmpty(answers.discussAfter.trim()))
    menteeDetails.discussAfter = answers.discussAfter;
  if (!isEmpty(answers.careerGoals.trim()))
    menteeDetails.careerGoals = answers.careerGoals;
  if (answers.skillMentorship.length > 0)
    menteeDetails.skillMentorship = answers.skillMentorship;
  if (answers.researchAreas.length > 0)
    menteeDetails.researchAreas = answers.researchAreas;
  if (answers.careerAdvice.length > 0)
    menteeDetails.careerAdvice = answers.careerAdvice;
  if (!isEmpty(answers.workshopReviewer))
    menteeDetails.workshopReviewer = answers.workshopReviewer;
  if (!isEmpty(answers.peerReviewedPubs.trim()))
    menteeDetails.peerReviewedPubs = answers.peerReviewedPubs;
  if (!isEmpty(answers.topTierReviewer.trim()))
    menteeDetails.topTierReviewer = answers.topTierReviewer;
  if (!isEmpty(answers.topTierPub.trim()))
    menteeDetails.topTierPub = answers.topTierPub;
  if (!isEmpty(answers.highImpactReviewer.trim()))
    menteeDetails.highImpactReviewer = answers.highImpactReviewer;
  if (answers.conferencePreference.length > 0)
    menteeDetails.conferencePreference = answers.conferencePreference;
  if (!isEmpty(answers.otherConferences.trim())) {
    let conferences = answers.otherConferences.split(',');
    menteeDetails.conferencePreference =
      menteeDetails.conferencePreference.concat(conferences);
  }
  if (!isEmpty(answers.peerReviewedHighImpact))
    menteeDetails.peerReviewedHighImpact = answers.peerReviewedHighImpact;

  return menteeDetails;
};

// Mentee Details Updater - Checks for non-answers/blanks and return dict
exports.reduceMentorDetails = (data) => {
  const answers = data.body;
  let mentorDetails = {};

  // Things we can pull from the data.user or just geneate
  mentorDetails.createdAt = new Date().toISOString();
  mentorDetails.userId = data.user.uid;
  mentorDetails.email = data.user.email;
  mentorDetails.handle = data.user.handle;

  //Things we can pull from the user's info in the user collection
  mentorDetails.fullName = answers.fullName;
  mentorDetails.isLatinX = answers.isLatinX;
  mentorDetails.currentLocation = answers.currentLocation;

  // Questions we need to ask in the mentor sign up flow
  if (!isEmpty(answers.gender.trim())) mentorDetails.gender = answers.gender;
  if (!isEmpty(answers.countryOrigin.trim()))
    mentorDetails.countryOrigin = answers.countryOrigin;
  if (!isEmpty(answers.affiliation.trim()))
    mentorDetails.affiliation = answers.affiliation;
  if (!isEmpty(answers.position.trim()))
    mentorDetails.position = answers.position;
  if (!isEmpty(answers.scholarOrWebsite.trim())) {
    // If user doesn't include the http://
    if (answers.scholarOrWebsite.trim().substring(0, 4) !== 'http') {
      mentorDetails.scholarOrWebsite = `http://${answers.scholarOrWebsite.trim()}`;
    } else mentorDetails.scholarOrWebsite = answers.scholarOrWebsite;
  }
  if (answers.languages.length > 0) mentorDetails.languages = answers.languages;
  if (!isEmpty(answers.timezone.trim()))
    mentorDetails.timezone = answers.timezone;
  if (!isEmpty(answers.previousMentor.trim()))
    mentorDetails.previousMentor = answers.previousMentor;
  if (answers.mentorshipArea.length > 0)
    mentorDetails.mentorshipArea = answers.mentorshipArea;
  if (!isEmpty(answers.hoursAvailable.trim()))
    mentorDetails.hoursAvailable = answers.hoursAvailable;
  if (answers.menteePref.length > 0)
    mentorDetails.menteePref = answers.menteePref;
  if (!isEmpty(answers.otherPref.trim())) {
    let menteePrefs;
    let newPref;
    if (mentorDetails.menteePref.length !== 0)
      menteePrefs = mentorDetails.menteePref;
    else menteePrefs = [];
    newPref = answers.otherPref.split(',');
    menteePrefs = menteePrefs.concat(newPref);
    mentorDetails.menteePref = menteePrefs;
  }
  if (answers.prefferedOutcomes.length > 0)
    mentorDetails.prefferedOutcomes = answers.prefferedOutcomes;
  if (!isEmpty(answers.otherOutcomes.trim())) {
    let outcomes;
    let newPref;
    if (mentorDetails.prefferedOutcomes.length !== 0)
      outcomes = mentorDetails.prefferedOutcomes;
    else outcomes = [];
    newPref = answers.otherPref.split(',');
    outcomes = outcomes.concat(newPref);
    mentorDetails.prefferedOutcomes = outcomes;
  }
  if (!isEmpty(answers.discussAfter.trim()))
    mentorDetails.discussAfter = answers.discussAfter;
  if (answers.skillMentorship.length > 0)
    mentorDetails.skillMentorship = answers.skillMentorship;
  if (answers.researchAreas.length > 0)
    mentorDetails.researchAreas = answers.researchAreas;
  if (answers.careerAdvice.length > 0)
    mentorDetails.careerAdvice = answers.careerAdvice;
  if (!isEmpty(answers.workshopReviewer))
    mentorDetails.workshopReviewer = answers.workshopReviewer;
  if (!isEmpty(answers.peerReviewedPubs.trim()))
    mentorDetails.peerReviewedPubs = answers.peerReviewedPubs;
  if (!isEmpty(answers.topTierReviewer.trim()))
    mentorDetails.topTierReviewer = answers.topTierReviewer;
  if (!isEmpty(answers.topTierPub.trim()))
    mentorDetails.topTierPub = answers.topTierPub;
  if (!isEmpty(answers.highImpactReviewer.trim()))
    mentorDetails.highImpactReviewer = answers.highImpactReviewer;
  if (answers.conferencePreference.length > 0)
    mentorDetails.conferencePreference = answers.conferencePreference;
  if (!isEmpty(answers.otherConferences.trim())) {
    let otherconferences = answers.otherConferences.split(',');
    let conferences = mentorDetails.conferencePreference;
    conferences = conferences.concat(otherconferences);
    mentorDetails.conferencePreference = conferences;
  }
  if (!isEmpty(answers.peerReviewedHighImpact))
    mentorDetails.peerReviewedHighImpact = answers.peerReviewedHighImpact;

  return mentorDetails;
};
1
  • TMac were you ever able to figure out a solution, we just started seeing this message as well in a very similar circumstance Commented Feb 5, 2022 at 18:24

6 Answers 6

7

According to the error message, there isn't a whole lot of information about the problem you're presenting. I know you used firebase –-debug deploy to retrieve the error message, and it returned an error on the user code, but what I would advise is that you look into the issue by viewing the log using firebase functions:log, which would be a lot easier.

There will be a visible representation of the exact issue. It could be something as simple as a missing package in some cases.

You can also use the following: firebase functions:log --only <FUNCTION_NAME>

To have a better understanding of this command, you can access the Write and view logs.

Sign up to request clarification or add additional context in comments.

3 Comments

Yeah, so I've made it through a few issues and now I am on this one Error [ERR_PACKAGE_PATH_NOT_EXPORTED]: No "exports" main defined in /Users/tmac/Programing/HolbertonFinal/MentorMatchingApp/firebase-fuctions/functions/node_modules/firebase/package.json
According to the Firebase Admin SDK documentation, the following should be used to manage users: const admin = require("firebase-admin"); instead of const firebase = require('firebase'); The error could also be fixed by running 'npm update'.
This helped me to find my issue! (Missing necessary permission iam.serviceAccounts.actAs)
4

I had added a package I needed in functions/index.js to my frontend with

/projectroot $ npm install -s [package]

, in stead of going into the /functions folder with the terminal and add it there to the /functions/package.json for node.js

/projectroot/functions $ npm install -s [package]

Why it causes so much trouble is because things work fine in emulator developer modus, but when you deploy it only sais it has an error, but doesn't tell you what the problem is.

More info on this: Firebase function failing to deploy

Comments

1

The issue is the lock file is not included by default in the ignore list in the firebase.json, so it is shipped with your code. You should update your firebase.json like this:

{
  "functions": [
    {
      "source": "functions",
      "codebase": "default",
      "ignore": [
        "node_modules",
        ".git",
        "firebase-debug.log",
        "firebase-debug.*.log",
        "*.local",
        "pnpm-lock.yaml" // or package-lock.json
      ]
    }
  ]
}

Comments

0

Your firebase.json must include the following JSON code and it has to be similar to this in your case:

"hosting": {
    "public": "public",
    "rewrites" :[{
    "source" : "**",
    "function" : "api"
    }],
    "ignore": [
      "firebase.json",
      "**/.*",
      "**/node_modules/**"
    ]
  }

Comments

0

I checked your script for deploying As far as I know deploy structure, you need to mention about deploying on index file because when you run the deploy command for function, it will find the function on the index file first so you need to upgrade index file like this

exports.getMentors = getMenthors // from mentors.js
// you can other function here

Comments

0

My first deployment ever to my Firebase project failed with this error. All I did was retry deployment a few minutes later and it worked!

I had a couple warnings in my console mentioning Firebase needed a few minutes to be setup, and that I should try redeploying later.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.