Trying to export backup via admin.firestore.v1.FirestoreAdminClient on a Next.js API route. Error: Could not load the default credentials
Trying to export backup via admin.firestore.v1.FirestoreAdminClient on a Next.js API route. Error: Could not load the default credentials
我正在尝试运行此代码来实施 Firestore 备份。
但这是我第一次将其部署到 Next.js 项目中。
我会在我的 /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");
}
};
这是initializeFirebaseAdmin()
函数
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;
};
这是我遇到的错误:
Error: Could not load the default credentials. Browse to https://cloud.google.com/docs/authentication/getting-started for more information.
at GoogleAuth.getApplicationDefaultAsync (/var/task/node_modules/google-auth-library/build/src/auth/googleauth.js:173:19)
起初我只是使用credential
属性。然后我添加了 databaseURL
看它是否能解决问题,但仍然是相同的结果。
我想我正在正确初始化 firebase-admin
。不确定这里出了什么问题。
更新: 刚发现同样的代码在我的本地环境(开发中)上运行良好,但在我的 Next.js [=42 上不起作用=] 部署时的环境。可能出了什么问题?
在地狱般的日子后,才发现我做错了什么。
我正在使用 new admin.firestore.v1.FirestoreAdminClient();
,因为 firebase-admin
本身不会公开任何方法供我们访问 exportDocuments()
功能。
但事实是,当您像那样实例化 FirestoreAdminClient
时,它将无法访问您在 admin.initializeApp({credentials})
.
上使用的凭据
因此您需要将凭据传递给客户端,方法是:
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");
};
我正在尝试运行此代码来实施 Firestore 备份。
但这是我第一次将其部署到 Next.js 项目中。
我会在我的 /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");
}
};
这是initializeFirebaseAdmin()
函数
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;
};
这是我遇到的错误:
Error: Could not load the default credentials. Browse to https://cloud.google.com/docs/authentication/getting-started for more information. at GoogleAuth.getApplicationDefaultAsync (/var/task/node_modules/google-auth-library/build/src/auth/googleauth.js:173:19)
起初我只是使用credential
属性。然后我添加了 databaseURL
看它是否能解决问题,但仍然是相同的结果。
我想我正在正确初始化 firebase-admin
。不确定这里出了什么问题。
更新: 刚发现同样的代码在我的本地环境(开发中)上运行良好,但在我的 Next.js [=42 上不起作用=] 部署时的环境。可能出了什么问题?
在地狱般的日子后,才发现我做错了什么。
我正在使用 new admin.firestore.v1.FirestoreAdminClient();
,因为 firebase-admin
本身不会公开任何方法供我们访问 exportDocuments()
功能。
但事实是,当您像那样实例化 FirestoreAdminClient
时,它将无法访问您在 admin.initializeApp({credentials})
.
因此您需要将凭据传递给客户端,方法是:
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");
};