繁体   English   中英

Firebase - 错误:部署函数时出错

[英]Firebase - Error: There was an error deploying functions

好吧,我在这里泡菜。 几天来,我一直在研究我的所有 firebase 功能,并认为我取得了非常好的进展,直到经过几天的 firebase 服务器和 Z03D476861AFD384510F2CB80CCFA851 测试后我去部署

当我使用 firebase --debug deploy 时,我在终端中遇到的错误是:

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
i  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

在这里阅读了其他一些帖子后,我对错误是什么以及在哪里可以找到它感到非常困惑。 firebase 服务在本地工作一切正常。 当我检查日志文件时,我得到了这个:


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":"timmcmackenjr@gmail.com"},"serviceName":"cloudfunctions.googleapis.com","methodName":"google.cloud.functions.v1.CloudFunctionsService.UpdateFunction","resourceName":"projects/lxai-mentor-matching/locations/us-central1/functions/api"}

这里的一篇文章是关于文件名中的空格,但这不是我的问题,另一篇文章是关于 package.json 所以我在这里发布我的但不确定我在找什么。 关于如何深入挖掘或寻找什么以便我可以再次部署工作的任何想法?

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

用户.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 });
    })
}

尖叫.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);
    })
};

被指导者.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 });
    })
}

导师.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 });
    })
}

验证器.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;
}

我添加了一个 package 我需要在 functions/index.js 到我的前端

/projectroot $ npm install -s [package]

,而不是使用终端进入 /functions 文件夹并将其添加到 /functions/package.json for node.js

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

为什么它会引起这么多麻烦是因为在模拟器开发人员模式下一切正常,但是当你部署它时,它只会说它有一个错误,但并没有告诉你问题是什么。

有关此的更多信息: Firebase function 未能部署

根据错误消息,关于该问题的信息并不多。 我知道您使用firebase –debug deploy来检索错误消息,它在用户代码上返回错误,但我建议您通过使用firebase functions:log ,这将是容易得多。

将有确切问题的可见表示。 在某些情况下,它可能就像缺少 package 一样简单。

您还可以使用以下内容: firebase functions:log --only <FUNCTION_NAME>

要更好地理解此命令,您可以访问写入和查看日志。

您的firebase.json必须包含以下 JSON 代码,并且在您的情况下它必须与此类似:

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM