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;
};