[英]Trying to export backup via admin.firestore.v1.FirestoreAdminClient on a Next.js API route. Error: Could not load the default credentials
I'm trying to run this code to implement a Firestore backup.我正在尝试运行此代码来实现 Firestore 备份。
But for the first time, I'm deploying it into a Next.js project.但这是我第一次将其部署到 Next.js 项目中。
I'll hit it on my /api/backup
endpoint.我将在我的
/api/backup
端点上点击它。
const backupHandler: NextApiHandler = async (req,res) => {
try {
const admin = initializeFirebaseAdmin();
const PROJECT_ID = getProjectId();
const client = new admin.firestore.v1.FirestoreAdminClient();
const DB_NAME = client.databasePath(PROJECT_ID, '(default)');
const TODAY = getToday(); // YYYY-MM-DD
const hashId = generateId().slice(0,5);
const BUCKET = `gs://${PROJECT_ID}.appspot.com`;
const FOLDER = `firestore-backup/${TODAY}-${hashId}`;
const FULL_PATH = `${BUCKET}/${FOLDER}`;
await client.exportDocuments({
name: DB_NAME,
outputUriPrefix: FULL_PATH,
collectionIds: [] // CAN LIST SPECIFIC COLLECTIONS
});
console.log(`Backup successfully exported`);
return res.status(200).send("Ok");
}
catch(err) {
console.log(err);
return res.status(500).send("Server error");
}
};
This is the initializeFirebaseAdmin()
function这是
initializeFirebaseAdmin()
function
type FirebaseAdmin = typeof import("firebase-admin/lib/firebase-namespace")
const getServiceAccount = () : admin.ServiceAccount => {
if (process.env.VERCEL_ENV === "production"
|| process.env.VERCEL_GIT_COMMIT_REF === "staging") {
return SERVICE_ACCOUNT.PROD;
}
else return SERVICE_ACCOUNT.TEST;
};
export const initializeFirebaseAdmin = (): FirebaseAdmin => {
const account = getServiceAccount(); // THIS GETS THE SERVICE ACOUNT (VIA THE DOWNLOADED .json FILE)
const PROJECT_ID = getProjectId();
if (!admin.apps.length) {
admin.initializeApp({
credential: admin.credential.cert(account),
databaseURL: `https://${PROJECT_ID}.firebaseio.com` // I TRIED WITH AND WITHOUT THIS LINE: SAME RESULT
});
}
return admin;
};
This is the error I'm getting:这是我得到的错误:
Error: Could not load the default credentials.
错误:无法加载默认凭据。 Browse to https://cloud.google.com/docs/authentication/getting-started for more information.
浏览到https://cloud.google.com/docs/authentication/getting-started了解更多信息。 at GoogleAuth.getApplicationDefaultAsync (/var/task/node_modules/google-auth-library/build/src/auth/googleauth.js:173:19)
在 GoogleAuth.getApplicationDefaultAsync (/var/task/node_modules/google-auth-library/build/src/auth/googleauth.js:173:19)
At first I was just using the credential
property.起初我只是使用
credential
属性。 Then I added the databaseURL
to see if it would solve the issue, but still, same result.然后我添加了
databaseURL
以查看它是否可以解决问题,但仍然是相同的结果。
I think I'm initializing the firebase-admin
properly.我想我正在正确初始化
firebase-admin
。 Not sure what is going wrong here.不知道这里出了什么问题。
UPDATE: Just found out that this very same code works fine on my local environment (in development), but does not work on my Next.js Node.js environment when I deploy it.更新:刚刚发现这个相同的代码在我的本地环境(开发中)上运行良好,但在我部署它时不适用于我的 Next.js Node.js 环境。 What could be going wrong?
可能出了什么问题?
After days in hell, just found out what I was doing wrong.在地狱里待了几天之后,才发现我做错了什么。
I'm using new admin.firestore.v1.FirestoreAdminClient();
我正在使用
new admin.firestore.v1.FirestoreAdminClient();
because firebase-admin
itself won't expose any methods for us to access the exportDocuments()
functionality.因为
firebase-admin
本身不会公开任何方法让我们访问exportDocuments()
功能。
But the fact is, when you instantiate the FirestoreAdminClient
like that, it will not have access to the credentials that you've used on admin.initializeApp({credentials})
.但事实是,当您像这样实例化
FirestoreAdminClient
时,它将无法访问您在admin.initializeApp({credentials})
上使用的凭据。
So you need to pass the credentials to the client, by doing:因此,您需要通过执行以下操作将凭据传递给客户端:
import * as admin from "firebase-admin"; // OR IMPORT IT FROM SOME SINGLETON initializeFirebaseAdmin FUNCTION
import { NextApiHandler } from "next";
import SERVICE_ACCOUNT from "some-path/serviceAccount.json";
interface CredentialBody { // COPIED THIS FROM google-auth-library > auth > credentials
client_email?: string;
private_key?: string;
}
const backupHandler: NextApiHandler = async (req,res) => {
const client = new admin.firestore.v1.FirestoreAdminClient({
credentials: SERVICE_ACCOUNT as CredentialBody // <<<<<< THIS IS THE IMPORTANT PART
});
const PROJECT_ID = getProjectId();
const DB_NAME = client.databasePath(PROJECT_ID, "(default)");
const TODAY = getToday(); // YYYY-MM-DD
const hashId = generateId().slice(0,5);
const BUCKET = `gs://${PROJECT_ID}.appspot.com`;
const FOLDER = `backup/${TODAY}-${hashId}`;
const FULL_PATH = `${BUCKET}/${FOLDER}`;
await client.exportDocuments({
name: DB_NAME,
outputUriPrefix: FULL_PATH,
collectionIds: [] // CAN LIST SPECIFIC COLLECTIONS
});
console.log(`Backup successfully exported`);
return res.status(200).send("Ok");
};
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.