Reputation: 117
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;
};
Upvotes: 7
Views: 11176
Reputation: 608
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/**"
]
}
Upvotes: 0
Reputation: 1197
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.
Upvotes: 5
Reputation: 1504
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
Upvotes: 4