123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208 |
- "use strict";
- Object.defineProperty(exports, "__esModule", { value: true });
- exports.HubExport = void 0;
- const path = require("path");
- const fs = require("fs");
- const fse = require("fs-extra");
- const http = require("http");
- const logger_1 = require("../logger");
- const types_1 = require("./types");
- const registry_1 = require("./registry");
- const error_1 = require("../error");
- const hub_1 = require("./hub");
- const downloadableEmulators_1 = require("./downloadableEmulators");
- const rimraf = require("rimraf");
- const track_1 = require("../track");
- class HubExport {
- constructor(projectId, options) {
- this.projectId = projectId;
- this.options = options;
- this.exportPath = options.path;
- this.tmpDir = fs.mkdtempSync(`firebase-export-${new Date().getTime()}`);
- }
- static readMetadata(exportPath) {
- const metadataPath = path.join(exportPath, this.METADATA_FILE_NAME);
- if (!fs.existsSync(metadataPath)) {
- return undefined;
- }
- return JSON.parse(fs.readFileSync(metadataPath, "utf8").toString());
- }
- async exportAll() {
- const toExport = types_1.ALL_EMULATORS.filter(shouldExport);
- if (toExport.length === 0) {
- throw new error_1.FirebaseError("No running emulators support import/export.");
- }
- const metadata = {
- version: hub_1.EmulatorHub.CLI_VERSION,
- };
- if (shouldExport(types_1.Emulators.FIRESTORE)) {
- metadata.firestore = {
- version: (0, downloadableEmulators_1.getDownloadDetails)(types_1.Emulators.FIRESTORE).version,
- path: "firestore_export",
- metadata_file: "firestore_export/firestore_export.overall_export_metadata",
- };
- await this.exportFirestore(metadata);
- }
- if (shouldExport(types_1.Emulators.DATABASE)) {
- metadata.database = {
- version: (0, downloadableEmulators_1.getDownloadDetails)(types_1.Emulators.DATABASE).version,
- path: "database_export",
- };
- await this.exportDatabase(metadata);
- }
- if (shouldExport(types_1.Emulators.AUTH)) {
- metadata.auth = {
- version: hub_1.EmulatorHub.CLI_VERSION,
- path: "auth_export",
- };
- await this.exportAuth(metadata);
- }
- if (shouldExport(types_1.Emulators.STORAGE)) {
- metadata.storage = {
- version: hub_1.EmulatorHub.CLI_VERSION,
- path: "storage_export",
- };
- await this.exportStorage(metadata);
- }
- if (!fs.existsSync(this.exportPath)) {
- fs.mkdirSync(this.exportPath);
- }
- void (0, track_1.trackEmulator)("emulator_export", {
- initiated_by: this.options.initiatedBy,
- emulator_name: types_1.Emulators.HUB,
- });
- const metadataPath = path.join(this.tmpDir, HubExport.METADATA_FILE_NAME);
- fs.writeFileSync(metadataPath, JSON.stringify(metadata, undefined, 2));
- logger_1.logger.debug(`hubExport: swapping ${this.tmpDir} with ${this.exportPath}`);
- rimraf.sync(this.exportPath);
- fse.moveSync(this.tmpDir, this.exportPath);
- }
- async exportFirestore(metadata) {
- void (0, track_1.trackEmulator)("emulator_export", {
- initiated_by: this.options.initiatedBy,
- emulator_name: types_1.Emulators.FIRESTORE,
- });
- const firestoreExportBody = {
- database: `projects/${this.projectId}/databases/(default)`,
- export_directory: this.tmpDir,
- export_name: metadata.firestore.path,
- };
- await registry_1.EmulatorRegistry.client(types_1.Emulators.FIRESTORE).post(`/emulator/v1/projects/${this.projectId}:export`, firestoreExportBody);
- }
- async exportDatabase(metadata) {
- const databaseEmulator = registry_1.EmulatorRegistry.get(types_1.Emulators.DATABASE);
- const client = registry_1.EmulatorRegistry.client(types_1.Emulators.DATABASE, { auth: true });
- const inspectURL = `/.inspect/databases.json`;
- const inspectRes = await client.get(inspectURL, {
- queryParams: { ns: this.projectId },
- });
- const namespaces = inspectRes.body.map((instance) => instance.name);
- const namespacesToExport = [];
- for (const ns of namespaces) {
- const checkDataPath = `/.json`;
- const checkDataRes = await client.get(checkDataPath, {
- queryParams: {
- ns,
- shallow: "true",
- limitToFirst: 1,
- },
- });
- if (checkDataRes.body !== null) {
- namespacesToExport.push(ns);
- }
- else {
- logger_1.logger.debug(`Namespace ${ns} contained null data, not exporting`);
- }
- }
- for (const ns of databaseEmulator.getImportedNamespaces()) {
- if (!namespacesToExport.includes(ns)) {
- logger_1.logger.debug(`Namespace ${ns} was imported, exporting.`);
- namespacesToExport.push(ns);
- }
- }
- void (0, track_1.trackEmulator)("emulator_export", {
- initiated_by: this.options.initiatedBy,
- emulator_name: types_1.Emulators.DATABASE,
- count: namespacesToExport.length,
- });
- const dbExportPath = path.join(this.tmpDir, metadata.database.path);
- if (!fs.existsSync(dbExportPath)) {
- fs.mkdirSync(dbExportPath);
- }
- const { host, port } = databaseEmulator.getInfo();
- for (const ns of namespacesToExport) {
- const exportFile = path.join(dbExportPath, `${ns}.json`);
- logger_1.logger.debug(`Exporting database instance: ${ns} to ${exportFile}`);
- await fetchToFile({
- host,
- port,
- path: `/.json?ns=${ns}&format=export`,
- headers: { Authorization: "Bearer owner" },
- }, exportFile);
- }
- }
- async exportAuth(metadata) {
- void (0, track_1.trackEmulator)("emulator_export", {
- initiated_by: this.options.initiatedBy,
- emulator_name: types_1.Emulators.AUTH,
- });
- const { host, port } = registry_1.EmulatorRegistry.get(types_1.Emulators.AUTH).getInfo();
- const authExportPath = path.join(this.tmpDir, metadata.auth.path);
- if (!fs.existsSync(authExportPath)) {
- fs.mkdirSync(authExportPath);
- }
- const accountsFile = path.join(authExportPath, "accounts.json");
- logger_1.logger.debug(`Exporting auth users in Project ${this.projectId} to ${accountsFile}`);
- await fetchToFile({
- host,
- port,
- path: `/identitytoolkit.googleapis.com/v1/projects/${this.projectId}/accounts:batchGet?maxResults=-1`,
- headers: { Authorization: "Bearer owner" },
- }, accountsFile);
- const configFile = path.join(authExportPath, "config.json");
- logger_1.logger.debug(`Exporting project config in Project ${this.projectId} to ${accountsFile}`);
- await fetchToFile({
- host,
- port,
- path: `/emulator/v1/projects/${this.projectId}/config`,
- headers: { Authorization: "Bearer owner" },
- }, configFile);
- }
- async exportStorage(metadata) {
- const storageExportPath = path.join(this.tmpDir, metadata.storage.path);
- if (fs.existsSync(storageExportPath)) {
- fse.removeSync(storageExportPath);
- }
- fs.mkdirSync(storageExportPath, { recursive: true });
- const storageExportBody = {
- path: storageExportPath,
- initiatedBy: this.options.initiatedBy,
- };
- const res = await registry_1.EmulatorRegistry.client(types_1.Emulators.STORAGE).request({
- method: "POST",
- path: "/internal/export",
- headers: { "Content-Type": "application/json" },
- body: storageExportBody,
- responseType: "stream",
- resolveOnHTTPError: true,
- });
- if (res.status >= 400) {
- throw new error_1.FirebaseError(`Failed to export storage: ${await res.response.text()}`);
- }
- }
- }
- exports.HubExport = HubExport;
- HubExport.METADATA_FILE_NAME = "firebase-export-metadata.json";
- function fetchToFile(options, path) {
- const writeStream = fs.createWriteStream(path);
- return new Promise((resolve, reject) => {
- http
- .get(options, (response) => {
- response.pipe(writeStream, { end: true }).once("close", resolve);
- })
- .on("error", reject);
- });
- }
- function shouldExport(e) {
- return types_1.IMPORT_EXPORT_EMULATORS.includes(e) && registry_1.EmulatorRegistry.isRunning(e);
- }
|