/*! firebase-admin v8.9.2 */ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var url_1 = require("url"); var path = require("path"); var error_1 = require("../utils/error"); var validator = require("../utils/validator"); var api_request_1 = require("../utils/api-request"); /** * Internals of a Database instance. */ var DatabaseInternals = /** @class */ (function () { function DatabaseInternals() { this.databases = {}; } /** * Deletes the service and its associated resources. * * @return {Promise<()>} An empty Promise that will be fulfilled when the service is deleted. */ DatabaseInternals.prototype.delete = function () { for (var _i = 0, _a = Object.keys(this.databases); _i < _a.length; _i++) { var dbUrl = _a[_i]; var db = this.databases[dbUrl]; db.INTERNAL.delete(); } return Promise.resolve(undefined); }; return DatabaseInternals; }()); var DatabaseService = /** @class */ (function () { function DatabaseService(app) { this.INTERNAL = new DatabaseInternals(); if (!validator.isNonNullObject(app) || !('options' in app)) { throw new error_1.FirebaseDatabaseError({ code: 'invalid-argument', message: 'First argument passed to admin.database() must be a valid Firebase app instance.', }); } this.appInternal = app; } Object.defineProperty(DatabaseService.prototype, "app", { /** * Returns the app associated with this DatabaseService instance. * * @return {FirebaseApp} The app associated with this DatabaseService instance. */ get: function () { return this.appInternal; }, enumerable: true, configurable: true }); DatabaseService.prototype.getDatabase = function (url) { var dbUrl = this.ensureUrl(url); if (!validator.isNonEmptyString(dbUrl)) { throw new error_1.FirebaseDatabaseError({ code: 'invalid-argument', message: 'Database URL must be a valid, non-empty URL string.', }); } var db = this.INTERNAL.databases[dbUrl]; if (typeof db === 'undefined') { var rtdb = require('@firebase/database'); var version = require('../../package.json').version; db = rtdb.initStandalone(this.appInternal, dbUrl, version).instance; var rulesClient_1 = new DatabaseRulesClient(this.app, dbUrl); db.getRules = function () { return rulesClient_1.getRules(); }; db.getRulesJSON = function () { return rulesClient_1.getRulesJSON(); }; db.setRules = function (source) { return rulesClient_1.setRules(source); }; this.INTERNAL.databases[dbUrl] = db; } return db; }; DatabaseService.prototype.ensureUrl = function (url) { if (typeof url !== 'undefined') { return url; } else if (typeof this.appInternal.options.databaseURL !== 'undefined') { return this.appInternal.options.databaseURL; } throw new error_1.FirebaseDatabaseError({ code: 'invalid-argument', message: 'Can\'t determine Firebase Database URL.', }); }; return DatabaseService; }()); exports.DatabaseService = DatabaseService; var RULES_URL_PATH = '.settings/rules.json'; /** * A helper client for managing RTDB security rules. */ var DatabaseRulesClient = /** @class */ (function () { function DatabaseRulesClient(app, dbUrl) { var parsedUrl = new url_1.URL(dbUrl); parsedUrl.pathname = path.join(parsedUrl.pathname, RULES_URL_PATH); this.dbUrl = parsedUrl.toString(); this.httpClient = new api_request_1.AuthorizedHttpClient(app); } /** * Gets the currently applied security rules as a string. The return value consists of * the rules source including comments. * * @return {Promise} A promise fulfilled with the rules as a raw string. */ DatabaseRulesClient.prototype.getRules = function () { var _this = this; var req = { method: 'GET', url: this.dbUrl, }; return this.httpClient.send(req) .then(function (resp) { if (!resp.text) { throw new error_1.FirebaseAppError(error_1.AppErrorCodes.INTERNAL_ERROR, 'HTTP response missing data.'); } return resp.text; }) .catch(function (err) { throw _this.handleError(err); }); }; /** * Gets the currently applied security rules as a parsed JSON object. Any comments in * the original source are stripped away. * * @return {Promise} A promise fulfilled with the parsed rules source. */ DatabaseRulesClient.prototype.getRulesJSON = function () { var _this = this; var req = { method: 'GET', url: this.dbUrl, data: { format: 'strict' }, }; return this.httpClient.send(req) .then(function (resp) { return resp.data; }) .catch(function (err) { throw _this.handleError(err); }); }; /** * Sets the specified rules on the Firebase Database instance. If the rules source is * specified as a string or a Buffer, it may include comments. * * @param {string|Buffer|object} source Source of the rules to apply. Must not be `null` * or empty. * @return {Promise} Resolves when the rules are set on the Database. */ DatabaseRulesClient.prototype.setRules = function (source) { var _this = this; if (!validator.isNonEmptyString(source) && !validator.isBuffer(source) && !validator.isNonNullObject(source)) { var error = new error_1.FirebaseDatabaseError({ code: 'invalid-argument', message: 'Source must be a non-empty string, Buffer or an object.', }); return Promise.reject(error); } var req = { method: 'PUT', url: this.dbUrl, data: source, headers: { 'content-type': 'application/json; charset=utf-8', }, }; return this.httpClient.send(req) .then(function () { return; }) .catch(function (err) { throw _this.handleError(err); }); }; DatabaseRulesClient.prototype.handleError = function (err) { if (err instanceof api_request_1.HttpError) { return new error_1.FirebaseDatabaseError({ code: error_1.AppErrorCodes.INTERNAL_ERROR, message: this.getErrorMessage(err), }); } return err; }; DatabaseRulesClient.prototype.getErrorMessage = function (err) { var intro = 'Error while accessing security rules'; try { var body = err.response.data; if (body && body.error) { return intro + ": " + body.error.trim(); } } catch (_a) { // Ignore parsing errors } return intro + ": " + err.response.text; }; return DatabaseRulesClient; }());