/*! firebase-admin v8.9.2 */ "use strict"; /*! * Copyright 2017 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ Object.defineProperty(exports, "__esModule", { value: true }); var fs = require("fs"); var deep_copy_1 = require("./utils/deep-copy"); var error_1 = require("./utils/error"); var firebase_app_1 = require("./firebase-app"); var credential_1 = require("./auth/credential"); var validator = require("./utils/validator"); var DEFAULT_APP_NAME = '[DEFAULT]'; /** * Constant holding the environment variable name with the default config. * If the environment variable contains a string that starts with '{' it will be parsed as JSON, * otherwise it will be assumed to be pointing to a file. */ exports.FIREBASE_CONFIG_VAR = 'FIREBASE_CONFIG'; var globalAppDefaultCred; var globalCertCreds = {}; var globalRefreshTokenCreds = {}; /** * Internals of a FirebaseNamespace instance. */ var FirebaseNamespaceInternals = /** @class */ (function () { function FirebaseNamespaceInternals(firebase_) { this.firebase_ = firebase_; this.serviceFactories = {}; this.apps_ = {}; this.appHooks_ = {}; } /** * Initializes the FirebaseApp instance. * * @param {FirebaseAppOptions} options Optional options for the FirebaseApp instance. If none present * will try to initialize from the FIREBASE_CONFIG environment variable. * If the environment variable contains a string that starts with '{' * it will be parsed as JSON, * otherwise it will be assumed to be pointing to a file. * @param {string} [appName] Optional name of the FirebaseApp instance. * * @return {FirebaseApp} A new FirebaseApp instance. */ FirebaseNamespaceInternals.prototype.initializeApp = function (options, appName) { if (appName === void 0) { appName = DEFAULT_APP_NAME; } if (typeof options === 'undefined') { options = this.loadOptionsFromEnvVar(); options.credential = credential_1.getApplicationDefault(); } if (typeof appName !== 'string' || appName === '') { throw new error_1.FirebaseAppError(error_1.AppErrorCodes.INVALID_APP_NAME, "Invalid Firebase app name \"" + appName + "\" provided. App name must be a non-empty string."); } else if (appName in this.apps_) { if (appName === DEFAULT_APP_NAME) { throw new error_1.FirebaseAppError(error_1.AppErrorCodes.DUPLICATE_APP, 'The default Firebase app already exists. This means you called initializeApp() ' + 'more than once without providing an app name as the second argument. In most cases ' + 'you only need to call initializeApp() once. But if you do want to initialize ' + 'multiple apps, pass a second argument to initializeApp() to give each app a unique ' + 'name.'); } else { throw new error_1.FirebaseAppError(error_1.AppErrorCodes.DUPLICATE_APP, "Firebase app named \"" + appName + "\" already exists. This means you called initializeApp() " + 'more than once with the same app name as the second argument. Make sure you provide a ' + 'unique name every time you call initializeApp().'); } } var app = new firebase_app_1.FirebaseApp(options, appName, this); this.apps_[appName] = app; this.callAppHooks_(app, 'create'); return app; }; /** * Returns the FirebaseApp instance with the provided name (or the default FirebaseApp instance * if no name is provided). * * @param {string} [appName=DEFAULT_APP_NAME] Optional name of the FirebaseApp instance to return. * @return {FirebaseApp} The FirebaseApp instance which has the provided name. */ FirebaseNamespaceInternals.prototype.app = function (appName) { if (appName === void 0) { appName = DEFAULT_APP_NAME; } if (typeof appName !== 'string' || appName === '') { throw new error_1.FirebaseAppError(error_1.AppErrorCodes.INVALID_APP_NAME, "Invalid Firebase app name \"" + appName + "\" provided. App name must be a non-empty string."); } else if (!(appName in this.apps_)) { var errorMessage = (appName === DEFAULT_APP_NAME) ? 'The default Firebase app does not exist. ' : "Firebase app named \"" + appName + "\" does not exist. "; errorMessage += 'Make sure you call initializeApp() before using any of the Firebase services.'; throw new error_1.FirebaseAppError(error_1.AppErrorCodes.NO_APP, errorMessage); } return this.apps_[appName]; }; Object.defineProperty(FirebaseNamespaceInternals.prototype, "apps", { /* * Returns an array of all the non-deleted FirebaseApp instances. * * @return {Array} An array of all the non-deleted FirebaseApp instances */ get: function () { var _this = this; // Return a copy so the caller cannot mutate the array return Object.keys(this.apps_).map(function (appName) { return _this.apps_[appName]; }); }, enumerable: true, configurable: true }); /* * Removes the specified FirebaseApp instance. * * @param {string} appName The name of the FirebaseApp instance to remove. */ FirebaseNamespaceInternals.prototype.removeApp = function (appName) { if (typeof appName === 'undefined') { throw new error_1.FirebaseAppError(error_1.AppErrorCodes.INVALID_APP_NAME, "No Firebase app name provided. App name must be a non-empty string."); } var appToRemove = this.app(appName); this.callAppHooks_(appToRemove, 'delete'); delete this.apps_[appName]; }; /* * Registers a new service on this Firebase namespace. * * @param {string} serviceName The name of the Firebase service to register. * @param {FirebaseServiceFactory} createService A factory method to generate an instance of the Firebase service. * @param {object} [serviceProperties] Optional properties to extend this Firebase namespace with. * @param {AppHook} [appHook] Optional callback that handles app-related events like app creation and deletion. * @return {FirebaseServiceNamespace} The Firebase service's namespace. */ FirebaseNamespaceInternals.prototype.registerService = function (serviceName, createService, serviceProperties, appHook) { var _this = this; var errorMessage; if (typeof serviceName === 'undefined') { errorMessage = "No service name provided. Service name must be a non-empty string."; } else if (typeof serviceName !== 'string' || serviceName === '') { errorMessage = "Invalid service name \"" + serviceName + "\" provided. Service name must be a non-empty string."; } else if (serviceName in this.serviceFactories) { errorMessage = "Firebase service named \"" + serviceName + "\" has already been registered."; } if (typeof errorMessage !== 'undefined') { throw new error_1.FirebaseAppError(error_1.AppErrorCodes.INTERNAL_ERROR, "INTERNAL ASSERT FAILED: " + errorMessage); } this.serviceFactories[serviceName] = createService; if (appHook) { this.appHooks_[serviceName] = appHook; } var serviceNamespace; // The service namespace is an accessor function which takes a FirebaseApp instance // or uses the default app if no FirebaseApp instance is provided serviceNamespace = function (appArg) { if (typeof appArg === 'undefined') { appArg = _this.app(); } // Forward service instance lookup to the FirebaseApp return appArg[serviceName](); }; // ... and a container for service-level properties. if (serviceProperties !== undefined) { deep_copy_1.deepExtend(serviceNamespace, serviceProperties); } // Monkey-patch the service namespace onto the Firebase namespace this.firebase_[serviceName] = serviceNamespace; return serviceNamespace; }; /** * Calls the app hooks corresponding to the provided event name for each service within the * provided FirebaseApp instance. * * @param {FirebaseApp} app The FirebaseApp instance whose app hooks to call. * @param {string} eventName The event name representing which app hooks to call. */ FirebaseNamespaceInternals.prototype.callAppHooks_ = function (app, eventName) { var _this = this; Object.keys(this.serviceFactories).forEach(function (serviceName) { if (_this.appHooks_[serviceName]) { _this.appHooks_[serviceName](eventName, app); } }); }; /** * Parse the file pointed to by the FIREBASE_CONFIG_VAR, if it exists. * Or if the FIREBASE_CONFIG_ENV contains a valid JSON object, parse it directly. * If the environment variable contains a string that starts with '{' it will be parsed as JSON, * otherwise it will be assumed to be pointing to a file. */ FirebaseNamespaceInternals.prototype.loadOptionsFromEnvVar = function () { var config = process.env[exports.FIREBASE_CONFIG_VAR]; if (!validator.isNonEmptyString(config)) { return {}; } try { var contents = config.startsWith('{') ? config : fs.readFileSync(config, 'utf8'); return JSON.parse(contents); } catch (error) { // Throw a nicely formed error message if the file contents cannot be parsed throw new error_1.FirebaseAppError(error_1.AppErrorCodes.INVALID_APP_OPTIONS, 'Failed to parse app options file: ' + error); } }; return FirebaseNamespaceInternals; }()); exports.FirebaseNamespaceInternals = FirebaseNamespaceInternals; var firebaseCredential = { cert: function (serviceAccountPathOrObject, httpAgent) { var stringifiedServiceAccount = JSON.stringify(serviceAccountPathOrObject); if (!(stringifiedServiceAccount in globalCertCreds)) { globalCertCreds[stringifiedServiceAccount] = new credential_1.ServiceAccountCredential(serviceAccountPathOrObject, httpAgent); } return globalCertCreds[stringifiedServiceAccount]; }, refreshToken: function (refreshTokenPathOrObject, httpAgent) { var stringifiedRefreshToken = JSON.stringify(refreshTokenPathOrObject); if (!(stringifiedRefreshToken in globalRefreshTokenCreds)) { globalRefreshTokenCreds[stringifiedRefreshToken] = new credential_1.RefreshTokenCredential(refreshTokenPathOrObject, httpAgent); } return globalRefreshTokenCreds[stringifiedRefreshToken]; }, applicationDefault: function (httpAgent) { if (typeof globalAppDefaultCred === 'undefined') { globalAppDefaultCred = credential_1.getApplicationDefault(httpAgent); } return globalAppDefaultCred; }, }; /** * Global Firebase context object. */ var FirebaseNamespace = /** @class */ (function () { /* tslint:enable */ function FirebaseNamespace() { // Hack to prevent Babel from modifying the object returned as the default admin namespace. /* tslint:disable:variable-name */ this.__esModule = true; /* tslint:enable:variable-name */ this.credential = firebaseCredential; this.SDK_VERSION = '8.9.2'; /* tslint:disable */ // TODO(jwenger): Database is the only consumer of firebase.Promise. We should update it to use // use the native Promise and then remove this. this.Promise = Promise; this.INTERNAL = new FirebaseNamespaceInternals(this); } Object.defineProperty(FirebaseNamespace.prototype, "auth", { /** * Gets the `Auth` service namespace. The returned namespace can be used to get the * `Auth` service for the default app or an explicitly specified app. */ get: function () { var _this = this; var fn = function (app) { return _this.ensureApp(app).auth(); }; var auth = require('./auth/auth').Auth; return Object.assign(fn, { Auth: auth }); }, enumerable: true, configurable: true }); Object.defineProperty(FirebaseNamespace.prototype, "database", { /** * Gets the `Database` service namespace. The returned namespace can be used to get the * `Database` service for the default app or an explicitly specified app. */ get: function () { var _this = this; var fn = function (app) { return _this.ensureApp(app).database(); }; return Object.assign(fn, require('@firebase/database')); }, enumerable: true, configurable: true }); Object.defineProperty(FirebaseNamespace.prototype, "messaging", { /** * Gets the `Messaging` service namespace. The returned namespace can be used to get the * `Messaging` service for the default app or an explicitly specified app. */ get: function () { var _this = this; var fn = function (app) { return _this.ensureApp(app).messaging(); }; var messaging = require('./messaging/messaging').Messaging; return Object.assign(fn, { Messaging: messaging }); }, enumerable: true, configurable: true }); Object.defineProperty(FirebaseNamespace.prototype, "storage", { /** * Gets the `Storage` service namespace. The returned namespace can be used to get the * `Storage` service for the default app or an explicitly specified app. */ get: function () { var _this = this; var fn = function (app) { return _this.ensureApp(app).storage(); }; var storage = require('./storage/storage').Storage; return Object.assign(fn, { Storage: storage }); }, enumerable: true, configurable: true }); Object.defineProperty(FirebaseNamespace.prototype, "firestore", { /** * Gets the `Firestore` service namespace. The returned namespace can be used to get the * `Firestore` service for the default app or an explicitly specified app. */ get: function () { var _this = this; var fn = function (app) { return _this.ensureApp(app).firestore(); }; var firestore = require('@google-cloud/firestore'); fn = Object.assign(fn, firestore.Firestore); // `v1beta1` and `v1` are lazy-loaded in the Firestore SDK. We use the same trick here // to avoid triggering this lazy-loading upon initialization. Object.defineProperty(fn, 'v1beta1', { get: function () { return firestore.v1beta1; }, }); Object.defineProperty(fn, 'v1', { get: function () { return firestore.v1; }, }); return fn; }, enumerable: true, configurable: true }); Object.defineProperty(FirebaseNamespace.prototype, "instanceId", { /** * Gets the `InstanceId` service namespace. The returned namespace can be used to get the * `Instance` service for the default app or an explicitly specified app. */ get: function () { var _this = this; var fn = function (app) { return _this.ensureApp(app).instanceId(); }; var instanceId = require('./instance-id/instance-id').InstanceId; return Object.assign(fn, { InstanceId: instanceId }); }, enumerable: true, configurable: true }); Object.defineProperty(FirebaseNamespace.prototype, "projectManagement", { /** * Gets the `ProjectManagement` service namespace. The returned namespace can be used to get the * `ProjectManagement` service for the default app or an explicitly specified app. */ get: function () { var _this = this; var fn = function (app) { return _this.ensureApp(app).projectManagement(); }; var projectManagement = require('./project-management/project-management').ProjectManagement; return Object.assign(fn, { ProjectManagement: projectManagement }); }, enumerable: true, configurable: true }); Object.defineProperty(FirebaseNamespace.prototype, "securityRules", { /** * Gets the `SecurityRules` service namespace. The returned namespace can be used to get the * `SecurityRules` service for the default app or an explicitly specified app. */ get: function () { var _this = this; var fn = function (app) { return _this.ensureApp(app).securityRules(); }; var securityRules = require('./security-rules/security-rules').SecurityRules; return Object.assign(fn, { SecurityRules: securityRules }); }, enumerable: true, configurable: true }); /** * Initializes the FirebaseApp instance. * * @param {FirebaseAppOptions} [options] Optional options for the FirebaseApp instance. * If none present will try to initialize from the FIREBASE_CONFIG environment variable. * If the environment variable contains a string that starts with '{' it will be parsed as JSON, * otherwise it will be assumed to be pointing to a file. * @param {string} [appName] Optional name of the FirebaseApp instance. * * @return {FirebaseApp} A new FirebaseApp instance. */ FirebaseNamespace.prototype.initializeApp = function (options, appName) { return this.INTERNAL.initializeApp(options, appName); }; /** * Returns the FirebaseApp instance with the provided name (or the default FirebaseApp instance * if no name is provided). * * @param {string} [appName] Optional name of the FirebaseApp instance to return. * @return {FirebaseApp} The FirebaseApp instance which has the provided name. */ FirebaseNamespace.prototype.app = function (appName) { return this.INTERNAL.app(appName); }; Object.defineProperty(FirebaseNamespace.prototype, "apps", { /* * Returns an array of all the non-deleted FirebaseApp instances. * * @return {Array} An array of all the non-deleted FirebaseApp instances */ get: function () { return this.INTERNAL.apps; }, enumerable: true, configurable: true }); FirebaseNamespace.prototype.ensureApp = function (app) { if (typeof app === 'undefined') { app = this.app(); } return app; }; return FirebaseNamespace; }()); exports.FirebaseNamespace = FirebaseNamespace;