"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.listDatabaseInstances = exports.parseDatabaseLocation = exports.checkInstanceNameAvailable = exports.createInstance = exports.getDatabaseInstanceDetails = exports.populateInstanceDetails = exports.DatabaseLocation = exports.DatabaseInstanceState = exports.DatabaseInstanceType = exports.APP_LIST_PAGE_SIZE = exports.MGMT_API_VERSION = void 0; const apiv2_1 = require("../apiv2"); const constants_1 = require("../emulator/constants"); const error_1 = require("../error"); const logger_1 = require("../logger"); const api_1 = require("../api"); const utils = require("../utils"); exports.MGMT_API_VERSION = "v1beta"; exports.APP_LIST_PAGE_SIZE = 100; const TIMEOUT_MILLIS = 10000; const INSTANCE_RESOURCE_NAME_REGEX = /projects\/([^/]+?)\/locations\/([^/]+?)\/instances\/([^/]*)/; var DatabaseInstanceType; (function (DatabaseInstanceType) { DatabaseInstanceType["DATABASE_INSTANCE_TYPE_UNSPECIFIED"] = "unspecified"; DatabaseInstanceType["DEFAULT_DATABASE"] = "default_database"; DatabaseInstanceType["USER_DATABASE"] = "user_database"; })(DatabaseInstanceType = exports.DatabaseInstanceType || (exports.DatabaseInstanceType = {})); var DatabaseInstanceState; (function (DatabaseInstanceState) { DatabaseInstanceState["LIFECYCLE_STATE_UNSPECIFIED"] = "unspecified"; DatabaseInstanceState["ACTIVE"] = "active"; DatabaseInstanceState["DISABLED"] = "disabled"; DatabaseInstanceState["DELETED"] = "deleted"; })(DatabaseInstanceState = exports.DatabaseInstanceState || (exports.DatabaseInstanceState = {})); var DatabaseLocation; (function (DatabaseLocation) { DatabaseLocation["US_CENTRAL1"] = "us-central1"; DatabaseLocation["EUROPE_WEST1"] = "europe-west1"; DatabaseLocation["ASIA_SOUTHEAST1"] = "asia-southeast1"; DatabaseLocation["ANY"] = "-"; })(DatabaseLocation = exports.DatabaseLocation || (exports.DatabaseLocation = {})); const apiClient = new apiv2_1.Client({ urlPrefix: api_1.rtdbManagementOrigin, apiVersion: exports.MGMT_API_VERSION }); async function populateInstanceDetails(options) { options.instanceDetails = await getDatabaseInstanceDetails(options.project, options.instance); return Promise.resolve(); } exports.populateInstanceDetails = populateInstanceDetails; async function getDatabaseInstanceDetails(projectId, instanceName) { try { const response = await apiClient.request({ method: "GET", path: `/projects/${projectId}/locations/-/instances/${instanceName}`, timeout: TIMEOUT_MILLIS, }); return convertDatabaseInstance(response.body); } catch (err) { logger_1.logger.debug(err.message); const emulatorHost = process.env[constants_1.Constants.FIREBASE_DATABASE_EMULATOR_HOST]; if (emulatorHost) { return Promise.resolve({ name: instanceName, project: projectId, location: DatabaseLocation.ANY, databaseUrl: utils.getDatabaseUrl(emulatorHost, instanceName, ""), type: DatabaseInstanceType.DEFAULT_DATABASE, state: DatabaseInstanceState.ACTIVE, }); } throw new error_1.FirebaseError(`Failed to get instance details for instance: ${instanceName}. See firebase-debug.log for more details.`, { exit: 2, original: err, }); } } exports.getDatabaseInstanceDetails = getDatabaseInstanceDetails; async function createInstance(projectId, instanceName, location, databaseType) { try { const response = await apiClient.request({ method: "POST", path: `/projects/${projectId}/locations/${location}/instances`, queryParams: { databaseId: instanceName }, body: { type: databaseType }, timeout: TIMEOUT_MILLIS, }); return convertDatabaseInstance(response.body); } catch (err) { logger_1.logger.debug(err.message); return utils.reject(`Failed to create instance: ${instanceName}. See firebase-debug.log for more details.`, { code: 2, original: err, }); } } exports.createInstance = createInstance; async function checkInstanceNameAvailable(projectId, instanceName, databaseType, location) { var _a, _b, _c; if (!location) { location = DatabaseLocation.US_CENTRAL1; } try { await apiClient.request({ method: "POST", path: `/projects/${projectId}/locations/${location}/instances`, queryParams: { databaseId: instanceName, validateOnly: "true" }, body: { type: databaseType }, timeout: TIMEOUT_MILLIS, }); return { available: true }; } catch (err) { logger_1.logger.debug(`Invalid Realtime Database instance name: ${instanceName}.${err.message ? " " + err.message : ""}`); const errBody = err.context.body.error; if ((_c = (_b = (_a = errBody === null || errBody === void 0 ? void 0 : errBody.details) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.metadata) === null || _c === void 0 ? void 0 : _c.suggested_database_ids) { return { available: false, suggestedIds: errBody.details[0].metadata.suggested_database_ids.split(","), }; } throw new error_1.FirebaseError(`Failed to validate Realtime Database instance name: ${instanceName}.`, { original: err, }); } } exports.checkInstanceNameAvailable = checkInstanceNameAvailable; function parseDatabaseLocation(location, defaultLocation) { if (!location) { return defaultLocation; } switch (location.toLowerCase()) { case "us-central1": return DatabaseLocation.US_CENTRAL1; case "europe-west1": return DatabaseLocation.EUROPE_WEST1; case "asia-southeast1": return DatabaseLocation.ASIA_SOUTHEAST1; case "": return defaultLocation; default: throw new error_1.FirebaseError(`Unexpected location value: ${location}. Only us-central1, europe-west1, and asia-southeast1 locations are supported`); } } exports.parseDatabaseLocation = parseDatabaseLocation; async function listDatabaseInstances(projectId, location, pageSize = exports.APP_LIST_PAGE_SIZE) { const instances = []; try { let nextPageToken = ""; do { const queryParams = { pageSize }; if (nextPageToken) { queryParams.pageToken = nextPageToken; } const response = await apiClient.request({ method: "GET", path: `/projects/${projectId}/locations/${location}/instances`, queryParams, timeout: TIMEOUT_MILLIS, }); if (response.body.instances) { instances.push(...response.body.instances.map(convertDatabaseInstance)); } nextPageToken = response.body.nextPageToken; } while (nextPageToken); return instances; } catch (err) { logger_1.logger.debug(err.message); throw new error_1.FirebaseError(`Failed to list Firebase Realtime Database instances${location === DatabaseLocation.ANY ? "" : ` for location ${location}`}` + ". See firebase-debug.log for more info.", { exit: 2, original: err, }); } } exports.listDatabaseInstances = listDatabaseInstances; function convertDatabaseInstance(serverInstance) { if (!serverInstance.name) { throw new error_1.FirebaseError(`DatabaseInstance response is missing field "name"`); } const m = serverInstance.name.match(INSTANCE_RESOURCE_NAME_REGEX); if (!m || m.length !== 4) { throw new error_1.FirebaseError(`Error parsing instance resource name: ${serverInstance.name}, matches: ${m}`); } return { name: m[3], location: parseDatabaseLocation(m[2], DatabaseLocation.ANY), project: serverInstance.project, databaseUrl: serverInstance.databaseUrl, type: serverInstance.type, state: serverInstance.state, }; }