TMa*_*Mac 7 node.js express firebase google-cloud-platform
好吧,我现在陷入困境了。我已经花了几天的时间来研究我的所有 Firebase 功能,并认为我取得了非常好的进展,直到我在使用 Firebase 服务器和邮递员进行了几天的测试后开始部署......它不会部署 T_T
当我使用 firebase --debug 部署时,我在终端中遇到的错误是:
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
Run Code Online (Sandbox Code Playgroud)
在这里阅读了其他一些帖子后,我对错误是什么以及在哪里可以找到它感到非常困惑。一切都在本地与 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"}
Run Code Online (Sandbox Code Playgroud)
这里的一篇文章是关于文件名中的空格,但这不是我的问题,另一篇文章是关于 package.json 的,所以我在这里发布我的文章,但不确定我在寻找什么。关于如何深入挖掘或寻找什么以便我可以再次进行部署的任何想法?
包.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
}
Run Code Online (Sandbox Code Playgroud)
索引.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);
Run Code Online (Sandbox Code Playgroud)
用户.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 });
});
};
Run Code Online (Sandbox Code Playgroud)
尖叫.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);
});
};
Run Code Online (Sandbox Code Playgroud)
受训者.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 });
})
}
Run Code Online (Sandbox Code Playgroud)
导师.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 });
});
};
Run Code Online (Sandbox Code Playgroud)
验证器.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 ema
| 归档时间: |
|
| 查看次数: |
8963 次 |
| 最近记录: |